[gcov] Ignore blocks from another file

Constructs such as inline variables, #line, and #include can create
lexical blocks with a different filename.
GCOVProfiling and llvm-cov gcov currently don't handle such cases (see
GCOVLines::writeOut and GCOVFile::readGCNO) and would incorrectly
attribute the line number to the current file.

For now, ignore such blocks. Missing line execution counts is better
than wrong ones.
This commit is contained in:
Fangrui Song 2023-08-11 18:46:16 -07:00
parent 182de296f7
commit 1f34e282e8
2 changed files with 43 additions and 1 deletions

View File

@ -0,0 +1,40 @@
// RUN: rm -rf %t && split-file %s %t && cd %t
// RUN: %clangxx --coverage main.cpp -o t
// RUN: %run ./t
// RUN: llvm-cov gcov -t t-main. | FileCheck %s
//--- main.cpp
#include "a.h"
#include <stdio.h>
// CHECK: Runs:1
/// __cxx_global_var_init contains a block from a.h. Don't attribute its lines to main.cpp.
// CHECK-NOT: {{^ +[0-9]+:}}
inline auto *const inl_var_main = // CHECK: 1: [[#]]:inline auto
new A; // CHECK-NEXT: 1: [[#]]:
void foo(int x) { // CHECK-NEXT: 1: [[#]]:
if (x) { // CHECK-NEXT: 1: [[#]]:
#include "a.inc"
}
}
// CHECK-NOT: {{^ +[0-9]+:}}
int main(int argc, char *argv[]) { // CHECK: 1: [[#]]:int main
foo(1); // CHECK-NEXT: 1: [[#]]:
} // CHECK-NEXT: 1: [[#]]:
// CHECK-NOT: {{^ +[0-9]+:}}
// CHECK: Source:a.h
// CHECK: 1: 1:struct A
// CHECK-NOT: {{^ +[0-9]+:}}
//--- a.h
struct A { A() { } }; // CHECK: 2: [[#]]:struct A
inline auto *const inl_var_a =
new A;
/// TODO a.inc:1 should have line execution.
// CHECK-NOT: {{^ +[0-9]+:}}
//--- a.inc
puts("");

View File

@ -898,7 +898,9 @@ bool GCOVProfiler::emitProfileNotes(
if (Line == Loc.getLine()) continue;
Line = Loc.getLine();
if (SP != getDISubprogram(Loc.getScope()))
MDNode *Scope = Loc.getScope();
// TODO: Handle blocks from another file due to #line, #include, etc.
if (isa<DILexicalBlockFile>(Scope) || SP != getDISubprogram(Scope))
continue;
GCOVLines &Lines = Block.getFile(Filename);