New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
lcov --initial generates mis-hit for signature in function definition #30
Comments
I tried to reproduce the problem with GNU g++ 4.8.5 but the result was as expected: both test.info and base.info contain an execution count of 1 for lines 3 and 7. Could you run llvm-cov directly (via |
The resulting test.cpp.gcov does not flag lines 3 and 7 as being instrumented/hit:
Full output of the
|
It appears that the cause for this problem lies in geninfo's read_gcno_function_record() function that assumes that a function's starting line is always instrumented. This seems to be true for .gcno files generated by GCC, but not for those from LLVM. A fix needs some more thought though, as the internal data representation for a .gcno file currently doesn't have a dedicated place for reporting function starting lines. |
Wondering if there is any workaround for this? Initial capture indeed seems to assume that the function's starting line is instrumented, which then leads to false positives when they are marked as non-covered. Edit: it seems as simple as filtering out all lines (where
where there exists a previous line in this file saying
Is there any catch? (re: properly fixing it in lcov itself) |
Here's a sample script that "fixes" it, for those who need it working now: import argparse
import subprocess
def demangle(symbol):
return subprocess.check_output(['c++filt', '-n', symbol.strip()]).decode().strip()
def filter_lcov(lines, verbose=False):
defs, srcfile = {}, ''
for line in lines:
if line.startswith('SF:'):
defs = {}
srcfile = line[3:].strip()
elif line.startswith('end_of_record'):
defs = {}
elif line.startswith('FN:'):
lineno, symbol = line[3:].split(',')
defs[lineno] = demangle(symbol)
elif line.startswith('DA:'):
lineno = line[3:].split(',')[0]
if lineno in defs:
if verbose:
print(f'Ignoring: {srcfile}:{lineno}:{defs[lineno]}')
continue
yield line
def main():
p = argparse.ArgumentParser()
p.add_argument('input', type=str)
p.add_argument('output', type=str)
p.add_argument('--verbose', '-v', action='store_true')
args = p.parse_args()
with open(args.input, 'r') as fin:
lines = list(fin)
with open(args.output, 'w') as fout:
for line in filter_lcov(lines, verbose=args.verbose):
fout.write(line)
if __name__ == '__main__':
main() (It would be obviously nice to not have to do it manually, though...) |
Here's a faster version of your script that works with Objective-C++ sources and only demangles in verbose mode :) import argparse
import subprocess
def demangle(symbol):
p = subprocess.Popen(['c++filt','-n'], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
return p.communicate(input=symbol.encode())[0].decode().strip()
def filter_lcov(lines, verbose=False):
defs, srcfile = {}, ''
for line in lines:
if line.startswith('SF:'):
defs = {}
srcfile = line[3:].strip()
elif line.startswith('end_of_record'):
defs = {}
elif line.startswith('FN:'):
lineno, symbol = line[3:].split(',')
if verbose:
defs[lineno] = demangle(symbol)
else:
defs[lineno] = True
elif line.startswith('DA:'):
lineno = line[3:].split(',')[0]
if lineno in defs:
if verbose:
print(f'Ignoring: {srcfile}:{lineno}:{defs[lineno]}')
continue
yield line
def main():
p = argparse.ArgumentParser()
p.add_argument('input', type=str)
p.add_argument('output', type=str)
p.add_argument('--verbose', '-v', action='store_true')
args = p.parse_args()
with open(args.input, 'r') as fin:
lines = list(fin)
with open(args.output, 'w') as fout:
for line in filter_lcov(lines, verbose=args.verbose):
fout.write(line)
if __name__ == '__main__':
main() |
Can you release your workaround script with an open-source license? I want to use it. |
@Swift1313 I published my version of the python script with a public domain license at https://github.com/JeremyAgost/lcov-llvm-function-mishit-filter |
@aldanor Considering @JeremyAgost's script is based on your's, can you open-source that as well? Please? |
My g++ (arch linux) outputs the following Coverage Result
For me the last closing bracket will not count |
Here's a one-liner that should do the same thing as the Python scripts. Awk isn't my forte, so there may be an easier method. awk -F '[:,]' '/^SF:/ { delete defs } /^FN:/ { defs[$2]=1 } /^DA:/ { if ($3 == 0 && $2 in defs) next } { print }' Explanation: This is simple enough to place directly into a |
Hola, is there no fix for this yet? |
I have NOT tried to test with upstream and see if it’s fixed.
… On Mar 6, 2019, at 5:03 AM, popescu-af ***@***.***> wrote:
Hola, is there no fix for this yet?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub <#30 (comment)>, or mute the thread <https://github.com/notifications/unsubscribe-auth/AA02PO1zziq4E6G4A1wNt54h-wwMweAeks5vT5J3gaJpZM4Nkixx>.
|
This should fix a bug in the coverage computation in older clang versions (before LLVM 8) where the function signature is marked as uncovered: clang instruments incorrectly marks it as code. That is: void foo(void) // <- this line is marked as uncovered code { return 0; } See also - <https://stackoverflow.com/q/31507084> - <https://stackoverflow.com/q/47960954> - <linux-test-project/lcov#30>
This should fix a bug in the coverage computation in older clang versions (before LLVM 8) where the function signature is marked as uncovered: clang instruments incorrectly marks it as code. That is: void foo(void) // <- this line is marked as uncovered code { return 0; } See also - <https://stackoverflow.com/q/31507084> - <https://stackoverflow.com/q/47960954> - <linux-test-project/lcov#30>
Hi - Thanks |
The problem mentioned in #30 (comment) refers to lcov code that directly interprets binary Given the amount of effort that would be required to fix the |
Versions
Running
LCOV version 1.12
onmacOS Sierra 10.12.5
and g++Apple LLVM version 8.1.0 (clang-802.0.42)
Code snippet
Consider the following simple c++ code:
Coverage result
PROBLEM: lines 3 and 7 are reported executable but not hit, leading to mis coverage report.
Steps to reproduce
(where
covwrap.sh
is simply:Output
The text was updated successfully, but these errors were encountered: