Commit 1f34e282 authored by Fangrui Song's avatar Fangrui Song
Browse files

[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.
parent 182de296
Loading
Loading
Loading
Loading
+40 −0
Original line number Diff line number Diff line
// 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("");
+3 −1
Original line number Diff line number Diff line
@@ -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);