Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

Reading a tracefile with an uncalled gcc lambda aborts with an `inconsistent` error (or, with `--ignore-errors inconsistent`, marks the lambda called): `isLambda` matches only the demangled `{lambda(`, and geninfo writes mangled names by default

Open
#557 1 comment 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
48/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
perl

Research direction

Start by reading isLambda, _checkConsistency, and the geninfo name-writing path in lib/lcovutil.pm and bin/geninfo; the issue identifies the relevant line ranges and reproductions. Compare how mangled and demangled lambda names are handled, then run the five-line tracefile reproduction with and without --ignore-errors inconsistent. Done means reading the mangled tracefile preserves the uncalled count and emits no inconsistency error.

Written by the indexing model from the issue text.

Description

Versions

  • lcov 2.6, from the release tarball, and master at a4ba8b3. Also lcov 2.5.

  • The minimal reproduction needs no compiler.

  • Reproduced on:

    • macOS: the floor with 2.6 and master; the compiled example with gcc 16.2.0 and 2.6.
    • Ubuntu 24.04: the floor with 2.5 and an earlier master; the compiled example with gcc 15 and 2.5.

    Seen on real data from both, with 2.5.

Minimal reproduction

A five-line tracefile: one lambda that gcov says was never called, and a hit on its first line. That line runs when the closure is constructed. The two files differ only in how the name is spelled.

mangled.info:

SF:/nonexistent/m.cpp
FNL:0,5,5
FNA:0,0,_ZZ4mainENKUlvE_clEv
DA:5,1
end_of_record

demangled.info: the same, with FNA:0,0,main::{lambda()#1}::operator()() const.

Output abridged to the relevant lines:

$ lcov -a mangled.info -o out.info
lcov: ERROR: (corrupt) unable to read trace file 'mangled.info': lcov: ERROR: (inconsistent) "/nonexistent/m.cpp":5: function '_ZZ4mainENKUlvE_clEv' is not hit but line 5 is.
$ echo $?
1

$ lcov -a mangled.info -o out.info --ignore-errors inconsistent
lcov: WARNING: (inconsistent) "/nonexistent/m.cpp":5: function '_ZZ4mainENKUlvE_clEv' is not hit but line 5 is: function marked 'hit'.
$ grep FNA out.info
FNA:0,1,_ZZ4mainENKUlvE_clEv

$ lcov -a demangled.info -o out.info
$ grep FNA out.info
FNA:0,0,main::{lambda()#1}::operator()() const

lcov --summary, lcov --remove and genhtml read a tracefile the same way, and each behaves as lcov -a does.

How the data arises

template<class F> int call_if(bool b, F f) { return b ? f() : 0; }

int main(int argc, char**)
{
  return argc > 1 ? 2 : call_if(false, [] { return 1; });
}

With gcc 15 and its own gcov (the same with gcc 16, and with lcov 2.6):

g++-15 --coverage -O0 m.cpp -o m && ./m
lcov -c -d . -o cap.info --gcov-tool gcov-15
lcov -a cap.info -o read.info --ignore-errors inconsistent
  • The capture writes FNA:2,0,_ZZ4mainENKUlvE_clEv and DA:5,1, with no warning. The data is consistent: line 5 ran, the lambda did not.
  • read.info has FNA:2,1,_ZZ4mainENKUlvE_clEv, with the "function marked 'hit'" warning.
  • The same with --rc geninfo_unexecuted_blocks=1 at capture (checked with gcc 16).
  • With --demangle-cpp at capture, the read leaves the count at 0.

Expected

The count stays 0 and no message is issued. That is what the exemption at lib/lcovutil.pm:10759-10770 is for: "don't warn about the first line of a lambda: the decl may executed [sic] even if the lambda function itself is not called". It is also what happens to the same data when the name is demangled.

Actual

Without --ignore-errors inconsistent, lcov aborts on reading a tracefile that geninfo has just written, and reports it as corrupt. With it, the lambda is reported as called, with its first line's count. On our project's data (gcc 15, lcov 2.5), 36 lambda instantiations at 27 source locations are marked, all of them uncalled according to gcov.

Mechanism (line numbers from the 2.6 release tarball; master's lib/lcovutil.pm and bin/geninfo have the same)

  • The documentation implies a modern gcov needs no flag. lcovrc(5), under derive_function_end_line, says: "lambdas are identified via function name matching - so you must enable demangling if your toolchain is too old to report demangled names in the GCOV output". gcc's gcov does report demangled_name in its JSON. But geninfo keeps it only under --demangle-cpp, and otherwise writes the mangled name (bin/geninfo:2556-2557). So with a current gcc, the tracefile holds _ZZ4mainENKUlvE_clEv.
  • isLambda (lib/lcovutil.pm:7303-7315) recognises a C/C++ lambda only by the demangled spelling, $self->name() =~ /{lambda\(/, so it returns false.
  • _checkConsistency (:10716) then treats the lambda's first line as an ordinary hit line. It raises inconsistent. If that error is ignored, or --keep-going lets it pass, the lambda and its aliases are marked hit (:10784-10790, _fixFunction :10686-10714).
  • The capture does not mark the lambda. At capture, geninfo applies its default region filter, so C/C++ files take the filtering path. That path runs the check only when function end lines must be derived (:10922-10924, :11827-11851), and gcc supplies them. A read without --filter runs the check on every file (:11850). So a correct capture is changed by the first tool that reads it, or that tool aborts.
  • The other isLambda callers (:10532, :11831) and the alias-naming code in addAlias and removeAliases (:7423-7424, :7472-7475) test the same demangled spelling on the same names.

Possible fixes

  • Demangle the name before matching, with the demangler lcov already supports.
  • Or recognise the Itanium encoding of a closure type, Ul<params>E[<n>]_, with a real parse of the mangled name. A substring test for Ul would also match unrelated names.
  • Or have geninfo write the demangled name whenever gcov supplies one.

Workarounds

  • --rc check_data_consistency=0 on every tool that reads a tracefile. This also switches off the rest of the consistency checks.
  • --demangle-cpp at capture. This merges aliases differently, and exempts only the lambda's first line, so a multi-line lambda whose closing line runs code of the enclosing statement is still marked.
Dominant language
Shell
Stars
1.1k
Forks
272
Avg merge
1d 12h
Merged PRs (30d)
13

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from linux-test-project/lcov

All issues in linux-test-project/lcov

Similar issues

More Shell/Bash issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.