aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWentao Zhang <35722712+whentojump@users.noreply.github.com>2024-04-22 12:37:38 -0500
committerTom Stellard <tstellar@redhat.com>2024-04-30 11:10:27 -0700
commitaea091b70edaf5b53bdd37f5ee6351c1642b07cc (patch)
treec00511883113eb85b01b0486bb1d1544f5ad5d26
parent58648f334d62c00e22e2200746513126d4448425 (diff)
downloadllvm-aea091b70edaf5b53bdd37f5ee6351c1642b07cc.zip
llvm-aea091b70edaf5b53bdd37f5ee6351c1642b07cc.tar.gz
llvm-aea091b70edaf5b53bdd37f5ee6351c1642b07cc.tar.bz2
[clang][CoverageMapping] do not emit a gap region when either end doesn't have valid source locations (#89564)
Fixes #86998 (cherry picked from commit c1b6cca1214e7a9c14a30b81585dd8b81baeaa77)
-rw-r--r--clang/lib/CodeGen/CoverageMappingGen.cpp11
-rw-r--r--clang/test/CoverageMapping/statement-expression.c36
2 files changed, 44 insertions, 3 deletions
diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp
index 0c43317..ae4e6d4 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -1207,6 +1207,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()) {
@@ -1370,9 +1376,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(),
diff --git a/clang/test/CoverageMapping/statement-expression.c b/clang/test/CoverageMapping/statement-expression.c
new file mode 100644
index 0000000..5f9ab58
--- /dev/null
+++ b/clang/test/CoverageMapping/statement-expression.c
@@ -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,
+ };
+}