Skip to content

Commit

Permalink
[clang][CoverageMapping] do not emit a gap region when either end doe…
Browse files Browse the repository at this point in the history
…sn't have valid source locations (#89564)

Fixes #86998
  • Loading branch information
whentojump authored Apr 22, 2024
1 parent a6c0282 commit c1b6cca
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 3 deletions.
11 changes: 8 additions & 3 deletions clang/lib/CodeGen/CoverageMappingGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1208,6 +1208,12 @@ struct CounterCoverageMappingBuilder
/// Find a valid gap range between \p AfterLoc and \p BeforeLoc.
std::optional<SourceRange> findGapAreaBetween(SourceLocation AfterLoc,
SourceLocation BeforeLoc) {
// Some statements (like AttributedStmt and ImplicitValueInitExpr) don't
// have valid source locations. Do not emit a gap region if this is the case
// in either AfterLoc end or BeforeLoc end.
if (AfterLoc.isInvalid() || BeforeLoc.isInvalid())
return std::nullopt;

// If AfterLoc is in function-like macro, use the right parenthesis
// location.
if (AfterLoc.isMacroID()) {
Expand Down Expand Up @@ -1368,9 +1374,8 @@ struct CounterCoverageMappingBuilder
for (const Stmt *Child : S->children())
if (Child) {
// If last statement contains terminate statements, add a gap area
// between the two statements. Skipping attributed statements, because
// they don't have valid start location.
if (LastStmt && HasTerminateStmt && !isa<AttributedStmt>(Child)) {
// between the two statements.
if (LastStmt && HasTerminateStmt) {
auto Gap = findGapAreaBetween(getEnd(LastStmt), getStart(Child));
if (Gap)
fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(),
Expand Down
36 changes: 36 additions & 0 deletions clang/test/CoverageMapping/statement-expression.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// 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

// No crash for the following examples, where GNU Statement Expression extension
// could introduce region terminators (break, goto etc) before implicit
// initializers in a struct or an array.
// See https://github.com/llvm/llvm-project/pull/89564

struct Foo {
int field1;
int field2;
};

void f1(void) {
struct Foo foo = {
.field1 = ({
switch (0) {
case 0:
break; // A region terminator
}
0;
}),
// ImplicitValueInitExpr introduced here for .field2
};
}

void f2(void) {
int arr[3] = {
[0] = ({
goto L0; // A region terminator
L0:
0;
}),
// ImplicitValueInitExpr introduced here for subscript [1]
[2] = 0,
};
}

0 comments on commit c1b6cca

Please sign in to comment.