Skip to content

Commit aea091b

Browse files
whentojumptstellar
authored andcommitted
[clang][CoverageMapping] do not emit a gap region when either end doesn't have valid source locations (#89564)
Fixes #86998 (cherry picked from commit c1b6cca)
1 parent 58648f3 commit aea091b

File tree

2 files changed

+44
-3
lines changed

2 files changed

+44
-3
lines changed

clang/lib/CodeGen/CoverageMappingGen.cpp

+8-3
Original file line numberDiff line numberDiff line change
@@ -1207,6 +1207,12 @@ struct CounterCoverageMappingBuilder
12071207
/// Find a valid gap range between \p AfterLoc and \p BeforeLoc.
12081208
std::optional<SourceRange> findGapAreaBetween(SourceLocation AfterLoc,
12091209
SourceLocation BeforeLoc) {
1210+
// Some statements (like AttributedStmt and ImplicitValueInitExpr) don't
1211+
// have valid source locations. Do not emit a gap region if this is the case
1212+
// in either AfterLoc end or BeforeLoc end.
1213+
if (AfterLoc.isInvalid() || BeforeLoc.isInvalid())
1214+
return std::nullopt;
1215+
12101216
// If AfterLoc is in function-like macro, use the right parenthesis
12111217
// location.
12121218
if (AfterLoc.isMacroID()) {
@@ -1370,9 +1376,8 @@ struct CounterCoverageMappingBuilder
13701376
for (const Stmt *Child : S->children())
13711377
if (Child) {
13721378
// If last statement contains terminate statements, add a gap area
1373-
// between the two statements. Skipping attributed statements, because
1374-
// they don't have valid start location.
1375-
if (LastStmt && HasTerminateStmt && !isa<AttributedStmt>(Child)) {
1379+
// between the two statements.
1380+
if (LastStmt && HasTerminateStmt) {
13761381
auto Gap = findGapAreaBetween(getEnd(LastStmt), getStart(Child));
13771382
if (Gap)
13781383
fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// RUN: %clang_cc1 -mllvm -emptyline-comment-coverage=false -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only -main-file-name statement-expression.c %s
2+
3+
// No crash for the following examples, where GNU Statement Expression extension
4+
// could introduce region terminators (break, goto etc) before implicit
5+
// initializers in a struct or an array.
6+
// See https://github.com/llvm/llvm-project/pull/89564
7+
8+
struct Foo {
9+
int field1;
10+
int field2;
11+
};
12+
13+
void f1(void) {
14+
struct Foo foo = {
15+
.field1 = ({
16+
switch (0) {
17+
case 0:
18+
break; // A region terminator
19+
}
20+
0;
21+
}),
22+
// ImplicitValueInitExpr introduced here for .field2
23+
};
24+
}
25+
26+
void f2(void) {
27+
int arr[3] = {
28+
[0] = ({
29+
goto L0; // A region terminator
30+
L0:
31+
0;
32+
}),
33+
// ImplicitValueInitExpr introduced here for subscript [1]
34+
[2] = 0,
35+
};
36+
}

0 commit comments

Comments
 (0)