Skip to content

Commit f87a62f

Browse files
committed
compiler_wrappers-gcc.adb: fix handling of special filenames
1 parent 61bf0d0 commit f87a62f

File tree

7 files changed

+164
-9
lines changed

7 files changed

+164
-9
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
int
2+
bar (int c)
3+
{
4+
return c + 1;
5+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
int
2+
foo (int a, int b)
3+
{
4+
if (a)
5+
return a;
6+
else
7+
return b;
8+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
extern int foo (int a, int b);
2+
extern int bar (int c);
3+
4+
int
5+
main (void)
6+
{
7+
foo (0, 1);
8+
bar (0);
9+
return 0;
10+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
"""
2+
Check that the integration instrumentation handles correctly filenames that
3+
contain spaces.
4+
"""
5+
6+
import os
7+
import os.path
8+
9+
from e3.fs import cp
10+
11+
from SUITE.control import env
12+
from SUITE.cutils import Wdir
13+
from SCOV.minicheck import check_xcov_reports
14+
from SUITE.tutils import cmdrun, srctracename_for, thistest, xcov
15+
16+
Wdir("tmp_")
17+
18+
# Copy the sources in the temporary directory. Note that we cannot test the
19+
# case of a filename containing a double quote or a backslash on Windows
20+
# because of filename restrictions on that platform.
21+
copy_map = {
22+
"bar.c": 'src bar.c' if env.build.os.name == "windows" else 'src\\"bar.c',
23+
"foo.c": "src foo$@.c",
24+
"test.c": "test.c",
25+
}
26+
for src, dest in copy_map.items():
27+
cp(os.path.join("..", src), dest)
28+
29+
# Compute the expected coverage report from the actual source filenames. Note
30+
# that in xcov filenames, "gnatcov coverage" first turns '\' to '/' (during
31+
# path separator canonicalization) and then the unique filename machinery turns
32+
# '/' to '-'.
33+
coverage_data = {
34+
"test.c": {"+": {7, 8, 9}},
35+
"foo.c": {"+": {4, 7}, "-": {5}},
36+
"bar.c": {"+": {4}},
37+
}
38+
expected_report = {
39+
"{}.xcov".format(copy_map[filename].replace("\\", "-")): report
40+
for filename, report in coverage_data.items()
41+
}
42+
43+
# Setup the instrumentation process
44+
sources = [os.path.abspath(filename) for filename in copy_map.values()]
45+
files = [f"--files={filename}" for filename in sources]
46+
xcov(
47+
["setup-integration", "--level=stmt", "--compilers=gcc", "--output-dir=."]
48+
+ files
49+
)
50+
51+
# Shadow the compiler driver with the generated wrapper
52+
env.add_search_path(env_var="PATH", path=os.getcwd())
53+
54+
# Build the test program and run it
55+
cmdrun(["gcc", "-o", "test program"] + sources, for_pgm=False)
56+
cmdrun(["test program"], for_pgm=False)
57+
58+
# Check coverage expectations
59+
sid_args = [f"--sid={filename}.sid" for filename in sources]
60+
xcov(
61+
["coverage", "-cstmt", "-axcov", srctracename_for("test")]
62+
+ sid_args
63+
)
64+
check_xcov_reports("*.xcov", expected_report)
65+
66+
thistest.result()

tools/gnatcov/compiler_wrappers-gcc.adb

Lines changed: 52 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -213,20 +213,63 @@ is
213213
----------------
214214

215215
function Split_Args (Command : String) return String_Vectors.Vector is
216+
type State_Kind is
217+
(No_Argument, Simple_Argument, Quoted_Argument);
218+
219+
State : State_Kind := No_Argument;
216220
Arg : Unbounded_String;
217221
Result : String_Vectors.Vector;
218-
begin
219-
for C of Command loop
220-
if C = ' ' and then Arg /= "" then
222+
223+
procedure Append_Arg;
224+
225+
----------------
226+
-- Append_Arg --
227+
----------------
228+
229+
procedure Append_Arg is
230+
begin
231+
if State /= No_Argument then
221232
Result.Append (Arg);
233+
State := No_Argument;
222234
Arg := Null_Unbounded_String;
223-
else
224-
Append (Arg, C);
225235
end if;
236+
end Append_Arg;
237+
238+
C : Character;
239+
I : Natural := Command'First;
240+
241+
begin
242+
while I <= Command'Last loop
243+
C := Command (I);
244+
case State is
245+
when No_Argument =>
246+
if C = '"' then
247+
State := Quoted_Argument;
248+
elsif C /= ' ' then
249+
State := Simple_Argument;
250+
Append (Arg, C);
251+
end if;
252+
253+
when Simple_Argument =>
254+
if C = ' ' then
255+
Append_Arg;
256+
else
257+
Append (Arg, C);
258+
end if;
259+
260+
when Quoted_Argument =>
261+
if C = '\' then
262+
I := I + 1;
263+
Append (Arg, Command (I));
264+
elsif C = '"' then
265+
Append_Arg;
266+
else
267+
Append (Arg, C);
268+
end if;
269+
end case;
270+
I := I + 1;
226271
end loop;
227-
if Arg /= "" then
228-
Result.Append (Arg);
229-
end if;
272+
Append_Arg;
230273
return Result;
231274
end Split_Args;
232275

@@ -736,7 +779,7 @@ begin
736779
Fullname : constant String :=
737780
Ada.Directories.Full_Name (+Comp_Command.Filename);
738781
Simple_Name : constant String :=
739-
Ada.Directories.Simple_Name (+Comp_Command.Filename);
782+
Workaround_Simple_Name (+Comp_Command.Filename);
740783
Instr_Name : constant String := (+Prj.Output_Dir) / Simple_Name;
741784

742785
begin

tools/gnatcov/paths.adb

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,4 +317,22 @@ package body Paths is
317317
and then Path (Path'First + 1) = ':';
318318
end Starts_With_Drive_Pattern;
319319

320+
----------------------------
321+
-- Workaround_Simple_Name --
322+
----------------------------
323+
324+
function Workaround_Simple_Name (Path : String) return String is
325+
begin
326+
-- Return the Path suffix that precedes the first directory separator
327+
-- according to the current platform. Return the full string if there is
328+
-- no separator.
329+
330+
for I in reverse Path'Range loop
331+
if Path (I) = '/' or else (On_Windows and then Path (I) = '\') then
332+
return Path (I + 1 .. Path'Last);
333+
end if;
334+
end loop;
335+
return Path;
336+
end Workaround_Simple_Name;
337+
320338
end Paths;

tools/gnatcov/paths.ads

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,4 +66,9 @@ package Paths is
6666

6767
-- TODO??? Handle Unicode file names
6868

69+
function Workaround_Simple_Name (Path : String) return String;
70+
-- TODO??? (eng/toolchain/gnat#603) The native GNAT runtime has a bug on
71+
-- Unix systems: Ada.Directories.Simple_Name misbehaves in the presence of
72+
-- backslashes. Provide our own implementation as a workaround.
73+
6974
end Paths;

0 commit comments

Comments
 (0)