diff options
author | Jørgen Kvalsvik <j@lambda.is> | 2024-03-29 13:01:37 +0100 |
---|---|---|
committer | Jørgen Kvalsvik <j@lambda.is> | 2024-07-11 09:13:16 +0200 |
commit | 1e43ea7bb3598e3ee19119c54c69a7c4b8745d0f (patch) | |
tree | a386dd6db13eb8ac99c42d53040a9378a7d0b8c8 /gcc/doc | |
parent | 2b3fbac8e37384857cd594c0800fccd99e4d39a1 (diff) | |
download | gcc-1e43ea7bb3598e3ee19119c54c69a7c4b8745d0f.zip gcc-1e43ea7bb3598e3ee19119c54c69a7c4b8745d0f.tar.gz gcc-1e43ea7bb3598e3ee19119c54c69a7c4b8745d0f.tar.bz2 |
Add function filtering to gcov
Add the --include and --exclude flags to gcov to control what functions
to report on. This is meant to make gcov more practical as an when
writing test suites or performing other coverage experiments, which
tends to focus on a few functions at the time. This really shines in
combination with the -t/--stdout flag. With support for more expansive
metrics in gcov like modified condition/decision coverage (MC/DC) and
path coverage, output quickly gets overwhelming without filtering.
The approach is quite simple: filters are egrep regexes and are
evaluated left-to-right, and the last filter "wins", that is, if a
function matches an --include and a subsequent --exclude, it should not
be included in the output. All of the output machinery works on the
function table, so by optionally (not) adding function makes the even
the json output work as expected, and only minor changes are needed to
suppress the filtered-out functions.
Demo: math.c
int mul (int a, int b) {
return a * b;
}
int sub (int a, int b) {
return a - b;
}
int sum (int a, int b) {
return a + b;
}
Plain matches:
$ gcov -t math --include=sum
-: 0:Source:math.c
-: 0:Graph:math.gcno
-: 0:Data:-
-: 0:Runs:0
#####: 9:int sum (int a, int b) {
#####: 10: return a + b;
-: 11:}
$ gcov -t math --include=mul
-: 0:Source:math.c
-: 0:Graph:math.gcno
-: 0:Data:-
-: 0:Runs:0
#####: 1:int mul (int a, int b) {
#####: 2: return a * b;
-: 3:}
Regex match:
$ gcov -t math --include=su
-: 0:Source:math.c
-: 0:Graph:math.gcno
-: 0:Data:-
-: 0:Runs:0
#####: 5:int sub (int a, int b) {
#####: 6: return a - b;
-: 7:}
#####: 9:int sum (int a, int b) {
#####: 10: return a + b;
-: 11:}
And similar for exclude:
$ gcov -t math --exclude=sum
-: 0:Source:math.c
-: 0:Graph:math.gcno
-: 0:Data:-
-: 0:Runs:0
#####: 1:int mul (int a, int b) {
#####: 2: return a * b;
-: 3:}
#####: 5:int sub (int a, int b) {
#####: 6: return a - b;
-: 7:}
And json, for good measure:
$ gcov -t math --include=sum --json | jq ".files[].lines[]"
{
"line_number": 9,
"function_name": "sum",
"count": 0,
"unexecuted_block": true,
"block_ids": [],
"branches": [],
"calls": []
}
{
"line_number": 10,
"function_name": "sum",
"count": 0,
"unexecuted_block": true,
"block_ids": [
2
],
"branches": [],
"calls": []
}
Matching generally work well for mangled names, as the mangled names
also have the base symbol name in it. By default, functions are matched
by the mangled name, which means matching on base names always work as
expected. The -M flag makes the matching work on the demangled name
which is quite useful when you only want to report on specific
overloads and can use the full type names.
Why not just use grep? grep is not really sufficient as grep is very
line oriented, and the reports that benefit the most from filtering
often unpredictably span multiple lines based on the state of coverage.
For example, a condition coverage report for 3 terms/6 outcomes only
outputs 1 line when all conditions are covered, and 7 with no lines
covered.
gcc/ChangeLog:
* doc/gcov.texi: Add --include, --exclude, --match-on-demangled
documentation.
* gcov.cc (struct fnfilter): New.
(print_usage): Add --include, --exclude, -M,
--match-on-demangled.
(process_args): Likewise.
(release_structures): Release filters.
(read_graph_file): Only add function_infos matching filters.
(output_lines): Likewise.
gcc/testsuite/ChangeLog:
* lib/gcov.exp: Add filtering test function.
* g++.dg/gcov/gcov-19.C: New test.
* g++.dg/gcov/gcov-20.C: New test.
* g++.dg/gcov/gcov-21.C: New test.
* gcc.misc-tests/gcov-25.c: New test.
* gcc.misc-tests/gcov-26.c: New test.
* gcc.misc-tests/gcov-27.c: New test.
* gcc.misc-tests/gcov-28.c: New test.
Diffstat (limited to 'gcc/doc')
-rw-r--r-- | gcc/doc/gcov.texi | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/gcc/doc/gcov.texi b/gcc/doc/gcov.texi index fa5bdd3..a922173 100644 --- a/gcc/doc/gcov.texi +++ b/gcc/doc/gcov.texi @@ -127,11 +127,14 @@ gcov [@option{-v}|@option{--version}] [@option{-h}|@option{--help}] [@option{-g}|@option{--conditions}] [@option{-d}|@option{--display-progress}] [@option{-f}|@option{--function-summaries}] + [@option{--include} @var{regex}] + [@option{--exclude} @var{regex}] [@option{-j}|@option{--json-format}] [@option{-H}|@option{--human-readable}] [@option{-k}|@option{--use-colors}] [@option{-l}|@option{--long-file-names}] [@option{-m}|@option{--demangled-names}] + [@option{-M}|@option{--filter-on-demangled}] [@option{-n}|@option{--no-output}] [@option{-o}|@option{--object-directory} @var{directory|file}] [@option{-p}|@option{--preserve-paths}] @@ -186,6 +189,24 @@ Display the progress on the standard output. @itemx --function-summaries Output summaries for each function in addition to the file level summary. +@item --include @var{regex} +Include functions matching @var{regex}. This option makes +@command{gcov} only report on functions that match the extended +regular expression @var{regex}. This flag can be combined with +@option{--exclude}. If a function matches both includes and excludes, +the last include/exclude applies. By default @command{gcov} reports +on all functions, but if a @command{--include} is used then only +functions matching the include will be reported. + +@item --exclude @var{regex} +Exclude functions matching @var{regex}. This option makes +@command{gcov} not report on functions that match the extended regular +expression @var{regex}. This flag can be combined with +@option{--include}. If a function matches both includes and excludes, +the last include/exclude applies. By default @command{gcov} reports +on all functions, and if @option{--exclude} is used then functions +matching it will be omitted. + @item -h @itemx --help Display help about using @command{gcov} (on the standard output), and @@ -449,6 +470,12 @@ and included file names will be complete path names. Display demangled function names in output. The default is to show mangled function names. +@item -M +@itemx --filter-on-demangled +Make @option{--include} and @option{--exclude} match demangled names. +This does only affects the matching and does not imply +@option{--demangled-names}, but it can safely be combined with it. + @item -n @itemx --no-output Do not create the @command{gcov} output file. @@ -978,6 +1005,92 @@ the file doesn't match the executable (differing number of basic block counts) it will ignore the contents of the file. It then adds in the new execution counts and finally writes the data to the file. +You can report on a subset of functions by using @option{--include} +and @option{--exclude}. This is very useful when combined with +@option{--stdout} trying to understand behavior and coverage for a +particular function by running a test, looking at @command{gcov} +output, testing another input, and running @command{gcov} again. + +@smallexample +$ gcov -m --stdout --include inc tmp + -: 0:Source:tmp.cpp + -: 0:Graph:tmp.gcno + -: 0:Data:tmp.gcda + -: 0:Runs:1 + 2*: 8: void inc () @{ b++; @} +------------------ +Foo<char>::inc(): + #####: 8: void inc () @{ b++; @} +------------------ +Foo<int>::inc(): + 2: 8: void inc () @{ b++; @} +------------------ +@end smallexample + +@command{gcov} will match on mangled names by default, which you can +control with the @option{-M} flag. Note that matching and reporting +are independent, so you can match on mangled names while printing +demangled names, and vice versa. To report on the @code{int} +instantiation of @code{Foo} matching on mangled and demangled names: + +@smallexample +$ gcov -t -m -M tmp --include 'Foo<int>' + -: 0:Source:tmp.cpp + -: 0:Graph:tmp.gcno + -: 0:Data:tmp.gcda + -: 0:Runs:1 + 1: 7: Foo(): b (1000) @{@} + 2: 8: void inc () @{ b++; @} +@end smallexample + +@smallexample +$ gcov -t -m tmp --include 'FooIi' + -: 0:Source:tmp.cpp + -: 0:Graph:tmp.gcno + -: 0:Data:tmp.gcda + -: 0:Runs:1 + 1: 7: Foo(): b (1000) @{@} + 2: 8: void inc () @{ b++; @} +@end smallexample + +The arguments to @option{--include} and @option{--exclude} are +extended regular expressions (like @command{grep -E}), so the pattern +@code{in.?} matches both @code{inc} and @code{main}. If used with +@option{-M} then all @code{int} instantiations of @code{Foo} would +match too. @option{--include} and @option{--exclude} can be used +multiple times, and if a name matches multiple filters it is the last +one to match which takes preference. For example, to match +@code{main} and the @code{int} instatiation of @code{inc}, while +omitting the @code{Foo} constructor: + +@smallexample +$ gcov -t -m -M --include in --exclude Foo --include '<int>::inc' tmp + -: 0:Source:tmp.cpp + -: 0:Graph:tmp.gcno + -: 0:Data:tmp.gcda + -: 0:Runs:1 + 2: 8: void inc () @{ b++; @} + 1: 18:main (void) + -: 19:@{ + -: 20: int i, total; + 1: 21: Foo<int> counter; + -: 22: + 1: 23: counter.inc(); + 1: 24: counter.inc(); + 1: 25: total = 0; + -: 26: + 11: 27: for (i = 0; i < 10; i++) + 10: 28: total += i; + -: 29: + 1*: 30: int v = total > 100 ? 1 : 2; + -: 31: + 1: 32: if (total != 45) + #####: 33: printf ("Failure\n"); + -: 34: else + 1: 35: printf ("Success\n"); + 1: 36: return 0; +@end smallexample + @node Gcov and Optimization @section Using @command{gcov} with GCC Optimization |