Skip to content

[Coverage] Rework !SystemHeadersCoverage #91446

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

Merged
merged 2 commits into from
May 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 42 additions & 6 deletions clang/lib/CodeGen/CoverageMappingGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "clang/Basic/FileManager.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Lex/Lexer.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ProfileData/Coverage/CoverageMapping.h"
Expand Down Expand Up @@ -339,16 +340,26 @@ class CoverageMappingBuilder {

llvm::SmallSet<FileID, 8> Visited;
SmallVector<std::pair<SourceLocation, unsigned>, 8> FileLocs;
for (const auto &Region : SourceRegions) {
for (auto &Region : SourceRegions) {
SourceLocation Loc = Region.getBeginLoc();

// Replace Loc with FileLoc if it is expanded with system headers.
if (!SystemHeadersCoverage && SM.isInSystemMacro(Loc)) {
auto BeginLoc = SM.getSpellingLoc(Loc);
auto EndLoc = SM.getSpellingLoc(Region.getEndLoc());
if (SM.isWrittenInSameFile(BeginLoc, EndLoc)) {
Loc = SM.getFileLoc(Loc);
Region.setStartLoc(Loc);
Region.setEndLoc(SM.getFileLoc(Region.getEndLoc()));
}
}

FileID File = SM.getFileID(Loc);
if (!Visited.insert(File).second)
continue;

// Do not map FileID's associated with system headers unless collecting
// coverage from system headers is explicitly enabled.
if (!SystemHeadersCoverage && SM.isInSystemHeader(SM.getSpellingLoc(Loc)))
continue;
assert(SystemHeadersCoverage ||
!SM.isInSystemHeader(SM.getSpellingLoc(Loc)));

unsigned Depth = 0;
for (SourceLocation Parent = getIncludeOrExpansionLoc(Loc);
Expand Down Expand Up @@ -821,6 +832,10 @@ struct CounterCoverageMappingBuilder
/// A stack of currently live regions.
llvm::SmallVector<SourceMappingRegion> RegionStack;

/// Set if the Expr should be handled as a leaf even if it is kind of binary
/// logical ops (&&, ||).
llvm::DenseSet<const Stmt *> LeafExprSet;

/// An object to manage MCDC regions.
MCDCCoverageBuilder MCDCBuilder;

Expand Down Expand Up @@ -1043,7 +1058,10 @@ struct CounterCoverageMappingBuilder
// region onto RegionStack but immediately pop it (which adds it to the
// function's SourceRegions) because it doesn't apply to any other source
// code other than the Condition.
if (CodeGenFunction::isInstrumentedCondition(C)) {
// With !SystemHeadersCoverage, binary logical ops in system headers may be
// treated as instrumentable conditions.
if (CodeGenFunction::isInstrumentedCondition(C) ||
LeafExprSet.count(CodeGenFunction::stripCond(C))) {
mcdc::Parameters BranchParams;
mcdc::ConditionID ID = MCDCBuilder.getCondID(C);
if (ID >= 0)
Expand Down Expand Up @@ -2064,7 +2082,20 @@ struct CounterCoverageMappingBuilder
createDecisionRegion(E, DecisionParams);
}

/// Check if E belongs to system headers.
bool isExprInSystemHeader(const BinaryOperator *E) const {
return (!SystemHeadersCoverage &&
SM.isInSystemHeader(SM.getSpellingLoc(E->getOperatorLoc())) &&
SM.isInSystemHeader(SM.getSpellingLoc(E->getBeginLoc())) &&
SM.isInSystemHeader(SM.getSpellingLoc(E->getEndLoc())));
}

void VisitBinLAnd(const BinaryOperator *E) {
if (isExprInSystemHeader(E)) {
LeafExprSet.insert(E);
return;
}

bool IsRootNode = MCDCBuilder.isIdle();

// Keep track of Binary Operator and assign MCDC condition IDs.
Expand Down Expand Up @@ -2119,6 +2150,11 @@ struct CounterCoverageMappingBuilder
}

void VisitBinLOr(const BinaryOperator *E) {
if (isExprInSystemHeader(E)) {
LeafExprSet.insert(E);
return;
}

bool IsRootNode = MCDCBuilder.isIdle();

// Keep track of Binary Operator and assign MCDC condition IDs.
Expand Down
50 changes: 50 additions & 0 deletions clang/test/CoverageMapping/mcdc-system-headers.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// RUN: %clang_cc1 -std=c++11 -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -fcoverage-mcdc -mllvm -system-headers-coverage -emit-llvm-only -o - %s | FileCheck %s --check-prefixes=CHECK,W_SYS
// RUN: %clang_cc1 -std=c++11 -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -fcoverage-mcdc -emit-llvm-only -o - %s | FileCheck %s --check-prefixes=CHECK,X_SYS

#ifdef IS_SYSHEADER

#pragma clang system_header
#define CONST 42
#define EXPR1(x) (x)
#define EXPR2(x) ((x) && (x))

#else

#define IS_SYSHEADER
#include __FILE__

// CHECK: _Z5func0i:
int func0(int a) {
// CHECK: Decision,File 0, [[@LINE+3]]:11 -> [[@LINE+3]]:21 = M:0, C:2
// W_SYS: Expansion,File 0, [[@LINE+2]]:11 -> [[@LINE+2]]:16 = #0 (Expanded file = 1)
// X_SYS: Branch,File 0, [[@LINE+1]]:11 -> [[@LINE+1]]:11 = 0, 0 [1,2,0]
return (CONST && a);
// CHECK: Branch,File 0, [[@LINE-1]]:20 -> [[@LINE-1]]:21 = #2, (#1 - #2) [2,0,0]
// W_SYS: Branch,File 1, [[@LINE-16]]:15 -> [[@LINE-16]]:17 = 0, 0 [1,2,0]
}

// CHECK: _Z5func1ii:
int func1(int a, int b) {
// CHECK: Decision,File 0, [[@LINE+2]]:11 -> [[@LINE+2]]:21 = M:0, C:2
// CHECK: Branch,File 0, [[@LINE+1]]:11 -> [[@LINE+1]]:12 = (#0 - #1), #1 [1,0,2]
return (a || EXPR1(b));
// W_SYS: Expansion,File 0, [[@LINE-1]]:16 -> [[@LINE-1]]:21 = #1 (Expanded file = 1)
// W_SYS: Branch,File 1, [[@LINE-24]]:18 -> [[@LINE-24]]:21 = (#1 - #2), #2 [2,0,0]
// X_SYS: Branch,File 0, [[@LINE-3]]:16 -> [[@LINE-3]]:16 = (#1 - #2), #2 [2,0,0]
}

// CHECK: _Z5func2ii:
int func2(int a, int b) {
// W_SYS: Decision,File 0, [[@LINE+5]]:11 -> [[@LINE+5]]:28 = M:0, C:3
// X_SYS: Decision,File 0, [[@LINE+4]]:11 -> [[@LINE+4]]:28 = M:0, C:2
// W_SYS: Expansion,File 0, [[@LINE+3]]:11 -> [[@LINE+3]]:16 = #0 (Expanded file = 1)
// W_SYS: Expansion,File 0, [[@LINE+2]]:23 -> [[@LINE+2]]:28 = #1 (Expanded file = 2)
// X_SYS: Branch,File 0, [[@LINE+1]]:11 -> [[@LINE+1]]:11 = #1, (#0 - #1) [1,2,0]
return (EXPR2(a) && EXPR1(a));
// W_SYS: Branch,File 1, [[@LINE-35]]:19 -> [[@LINE-35]]:22 = #3, (#0 - #3) [1,3,0]
// W_SYS: Branch,File 1, [[@LINE-36]]:26 -> [[@LINE-36]]:29 = #4, (#3 - #4) [3,2,0]
// W_SYS: Branch,File 2, [[@LINE-38]]:18 -> [[@LINE-38]]:21 = #2, (#1 - #2) [2,0,0]
// X_SYS: Branch,File 0, [[@LINE-4]]:23 -> [[@LINE-4]]:23 = #2, (#1 - #2) [2,0,0]
}

#endif
Loading