Skip to content
Open
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
14 changes: 14 additions & 0 deletions changelog/dmd.cov-inline-pragma.dd
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
Coverage counters are now emitted at call sites of inlined functions

Functions marked `pragma(inline, true)` (and functions inlined via the
`-inline` flag) would always show `0000000` in `-cov` coverage reports
even when executed. The inlined function body is never called as a
standalone function at runtime - only the inlined copy inside the caller
runs, so its coverage counters stayed at zero.

Coverage counters are now emitted at each call site where a function is
inlined, so the function's lines correctly reflect how many times they
were executed.

Fixes $(LINK2 https://issues.dlang.org/show_bug.cgi?id=5848, Issue 5848) /
$(LINK2 https://github.com/dlang/dmd/issues/18337, #18337)
1 change: 1 addition & 0 deletions compiler/src/dmd/astbase.d
Original file line number Diff line number Diff line change
Expand Up @@ -5684,6 +5684,7 @@ struct ASTBase
extern (C++) final class CommaExp : BinExp
{
const bool isGenerated;
bool isInlineSequence;
bool allowCommaExp;

extern (D) this(Loc loc, Expression e1, Expression e2, bool generated = true)
Expand Down
3 changes: 3 additions & 0 deletions compiler/src/dmd/expression.d
Original file line number Diff line number Diff line change
Expand Up @@ -2828,6 +2828,9 @@ extern (C++) final class CommaExp : BinExp
/// to trigger the deprecation.
const bool isGenerated;

/// `true` if this comma chain was introduced by inline expansion.
bool isInlineSequence;

/// Temporary variable to enable / disable deprecation of comma expression
/// depending on the context.
/// Since most constructor calls are rewritting, the only place where
Expand Down
1 change: 1 addition & 0 deletions compiler/src/dmd/expression.h
Original file line number Diff line number Diff line change
Expand Up @@ -946,6 +946,7 @@ class CommaExp final : public BinExp
{
public:
d_bool isGenerated;
d_bool isInlineSequence;
d_bool allowCommaExp;
Expression* originalExp;
void accept(Visitor *v) override { v->visit(this); }
Expand Down
1 change: 1 addition & 0 deletions compiler/src/dmd/frontend.h
Original file line number Diff line number Diff line change
Expand Up @@ -2647,6 +2647,7 @@ class CommaExp final : public BinExp
{
public:
const bool isGenerated;
bool isInlineSequence;
Comment thread
dkorpel marked this conversation as resolved.
bool allowCommaExp;
Expression* originalExp;
void accept(Visitor* v) override;
Expand Down
19 changes: 19 additions & 0 deletions compiler/src/dmd/glue/e2ir.d
Original file line number Diff line number Diff line change
Expand Up @@ -3256,8 +3256,27 @@ elem* toElem(Expression e, ref IRState irs)
elem* visitComma(CommaExp ce)
{
assert(ce.e1 && ce.e2);
elem* inlineCoverage(Expression e)
{
if (!ce.isInlineSequence || !irs.params.cov || !e || !e.loc.isValid())
return null;

// Nested inline-sequence commas are accounted for recursively.
if (auto nested = e.isCommaExp())
{
if (nested.isInlineSequence)
return null;
}

return incUsageElem(irs, e.loc);
}

elem* eleft = toElem(ce.e1, irs);
eleft = el_combine(inlineCoverage(ce.e1), eleft);

elem* eright = toElem(ce.e2, irs);
eright = el_combine(inlineCoverage(ce.e2), eright);

elem* e = el_combine(eleft, eright);
if (e)
elem_setLoc(e, ce.loc);
Expand Down
23 changes: 17 additions & 6 deletions compiler/src/dmd/inline.d
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,15 @@ private final class InlineDoState
}
}

private Expression combineInlineSequence(Expression e1, Expression e2)
Comment thread
suyashkumar102 marked this conversation as resolved.
{
auto result = Expression.combine(e1, e2);
if (result)
if (auto ce = result.isCommaExp())
ce.isInlineSequence = true;
return result;
}

/***********************************************************
* Perform the inlining from (Statement or Expression) to (Statement or Expression).
*
Expand Down Expand Up @@ -218,13 +227,13 @@ public:
e2.type = Type.tvoid;
e.type = Type.tvoid;
}
result = Expression.combine(result, e);
result = combineInlineSequence(result, e);
}
else
{
ids.foundReturn = false;
auto e = doInlineAs!Expression(sx, ids);
result = Expression.combine(result, e);
result = combineInlineSequence(result, e);
}
}

Expand Down Expand Up @@ -253,7 +262,7 @@ public:
static if (asStatements)
as.push(r);
else
result = Expression.combine(result, r);
result = combineInlineSequence(result, r);

if (ids.foundReturn)
break;
Expand Down Expand Up @@ -2350,7 +2359,7 @@ private void expandInline(CallExp ecall, FuncDeclaration fd, FuncDeclaration par
ids.from.push(vfrom);
ids.to.push(vto);

auto de = new DeclarationExp(vto.loc, vto);
auto de = new DeclarationExp(Loc.initial, vto);
de.type = Type.tvoid;
eparams = Expression.combine(eparams, de);

Expand Down Expand Up @@ -2445,8 +2454,10 @@ private void expandInline(CallExp ecall, FuncDeclaration fd, FuncDeclaration par
e.type = Type.tvoid;
}

eresult = Expression.combine(eresult, eret, ethis, eparams);
eresult = Expression.combine(eresult, e);
eresult = combineInlineSequence(eresult, eret);
eresult = combineInlineSequence(eresult, ethis);
eresult = combineInlineSequence(eresult, eparams);
eresult = combineInlineSequence(eresult, e);

if (ecall.rvalue || tf.isRvalue)
eresult.rvalue = true;
Expand Down
26 changes: 26 additions & 0 deletions compiler/test/runnable/extra-files/runnable-test18337.lst
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
|// PERMUTE_ARGS:
|// REQUIRED_ARGS: -cov
|// POST_SCRIPT: runnable/extra-files/coverage-postscript.sh
|// EXECUTE_ARGS: ${RESULTS_DIR}/runnable
|
|extern(C) void dmd_coverDestPath(string path);
|
|pragma(inline, true)
|int square(int x)
|{
2| int y = x * x;
2| return y;
|}
|
|pragma(inline, true)
|int addSquares(int a, int b)
|{
1| return square(a) + square(b);
|}
|
|void main(string[] args)
|{
1| dmd_coverDestPath(args[1]);
1| auto value = addSquares(2, 3);
1| assert(value == 13);
|}
26 changes: 26 additions & 0 deletions compiler/test/runnable/test18337.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// PERMUTE_ARGS:
// REQUIRED_ARGS: -cov
// POST_SCRIPT: runnable/extra-files/coverage-postscript.sh
// EXECUTE_ARGS: ${RESULTS_DIR}/runnable

extern(C) void dmd_coverDestPath(string path);

pragma(inline, true)
int square(int x)
{
int y = x * x;
return y;
}

pragma(inline, true)
int addSquares(int a, int b)
{
return square(a) + square(b);
}

void main(string[] args)
{
dmd_coverDestPath(args[1]);
auto value = addSquares(2, 3);
assert(value == 13);
}
Loading