Skip to content

[clang][coverage] fixing "if constexpr" and "if consteval" coverage report #77214

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 1 commit into from
Jan 10, 2024

Conversation

hanickadot
Copy link
Contributor

@hanickadot hanickadot commented Jan 6, 2024

It was a while since I noticed coverage report is broken for "if constexpr" and "if consteval" (as shown on first picture).

Main problem was replacement of non-taken "if constexpr" branch with NullStmt but such object doesn't have begin/end for source location properly. So I introduced a new constructor for empty CompoundStmt and used it.

With "if consteval" I'm no longer introducing new branch counter for non-taken "branch". But in future it would be useful to mark whole gap there as skipped instead. If there is interest I would do it in another PR.

@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:codegen IR generation bugs: mangling, exceptions, etc. labels Jan 6, 2024
@llvmbot
Copy link
Member

llvmbot commented Jan 6, 2024

@llvm/pr-subscribers-clang-codegen

@llvm/pr-subscribers-clang

Author: Hana Dusíková (hanickadot)

Changes

It was a while since I noticed coverage report is broken for "if constexpr" and "if consteval" (as shown on first picture).
<img width="453" alt="Screenshot 2024-01-07 at 00 29 17" src="https://github.com/llvm/llvm-project/assets/6557263/dbdbc8a6-ad16-44da-882d-8e229ee69093">
(notice wrong coverage "if constexpr" for positive one, and completely missing for negative one, also notice "if consteval" marking always the same branch as uncovered)

Report after this change:
<img width="453" alt="Screenshot 2024-01-07 at 00 25 32" src="https://github.com/llvm/llvm-project/assets/6557263/d7ca85b0-34c7-40b5-9cc7-4efd8c18649b">

Main problem was replacement of non-taken "if constexpr" branch with NullStmt but such object doesn't have begin/end for source location properly. So I introduce a new constructor for empty CompoundStmt and used it.

With "if consteval" I'm no longer introducing new branch counter for non-taken "branch". But in future it would be useful to mark whole gap there as skipped instead. If there is interest I would do it in another PR.


Full diff: https://github.com/llvm/llvm-project/pull/77214.diff

3 Files Affected:

  • (modified) clang/include/clang/AST/Stmt.h (+4-2)
  • (modified) clang/lib/CodeGen/CoverageMappingGen.cpp (+11-2)
  • (modified) clang/lib/Sema/TreeTransform.h (+6-1)
diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h
index da7b37ce0e1211..fb50212083316e 100644
--- a/clang/include/clang/AST/Stmt.h
+++ b/clang/include/clang/AST/Stmt.h
@@ -1631,8 +1631,10 @@ class CompoundStmt final
                               SourceLocation RB);
 
   // Build an empty compound statement with a location.
-  explicit CompoundStmt(SourceLocation Loc)
-      : Stmt(CompoundStmtClass), LBraceLoc(Loc), RBraceLoc(Loc) {
+  explicit CompoundStmt(SourceLocation Loc) : CompoundStmt(Loc, Loc) {}
+
+  explicit CompoundStmt(SourceLocation Loc, SourceLocation EndLoc)
+      : Stmt(CompoundStmtClass), LBraceLoc(Loc), RBraceLoc(EndLoc) {
     CompoundStmtBits.NumStmts = 0;
     CompoundStmtBits.HasFPFeatures = 0;
   }
diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp
index bf227386a71b78..b245abd16c3f4a 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -1712,7 +1712,11 @@ struct CounterCoverageMappingBuilder
       extendRegion(S->getCond());
 
     Counter ParentCount = getRegion().getCounter();
-    Counter ThenCount = getRegionCounter(S);
+
+    // If this is "if !consteval" the then-branch will never be taken, we don't
+    // need to change counter
+    Counter ThenCount =
+        S->isNegatedConsteval() ? ParentCount : getRegionCounter(S);
 
     if (!S->isConsteval()) {
       // Emitting a counter for the condition makes it easier to interpret the
@@ -1729,7 +1733,12 @@ struct CounterCoverageMappingBuilder
     extendRegion(S->getThen());
     Counter OutCount = propagateCounts(ThenCount, S->getThen());
 
-    Counter ElseCount = subtractCounters(ParentCount, ThenCount);
+    // If this is "if consteval" the else-branch will never be taken, we don't
+    // need to change counter
+    Counter ElseCount = S->isNonNegatedConsteval()
+                            ? ParentCount
+                            : subtractCounters(ParentCount, ThenCount);
+
     if (const Stmt *Else = S->getElse()) {
       bool ThenHasTerminateStmt = HasTerminateStmt;
       HasTerminateStmt = false;
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index c8c5a51bf9f94e..0033c851b618a1 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -7732,7 +7732,8 @@ TreeTransform<Derived>::TransformIfStmt(IfStmt *S) {
     if (Then.isInvalid())
       return StmtError();
   } else {
-    Then = new (getSema().Context) NullStmt(S->getThen()->getBeginLoc());
+    Then = new (getSema().Context)
+        CompoundStmt(S->getThen()->getBeginLoc(), S->getThen()->getEndLoc());
   }
 
   // Transform the "else" branch.
@@ -7741,6 +7742,10 @@ TreeTransform<Derived>::TransformIfStmt(IfStmt *S) {
     Else = getDerived().TransformStmt(S->getElse());
     if (Else.isInvalid())
       return StmtError();
+  } else if (S->getElse() && ConstexprConditionValue &&
+             *ConstexprConditionValue) {
+    Else = new (getSema().Context)
+        CompoundStmt(S->getElse()->getBeginLoc(), S->getElse()->getEndLoc());
   }
 
   if (!getDerived().AlwaysRebuild() &&

@hanickadot
Copy link
Contributor Author

compare

(notice wrong coverage "if constexpr" for positive one, and completely missing for negative one, also notice "if consteval" marking always the same branch as uncovered)

Copy link
Contributor

@cor3ntin cor3ntin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the patch!

I think this might need a release note (referencing the couple open issues about this bug), and probably some tests.

@hanickadot
Copy link
Contributor Author

Fixes #54419.

@cor3ntin
Copy link
Contributor

cor3ntin commented Jan 7, 2024

Adding a few folks to the review (We do not seem to update the coverage mapping very often)

@chfast
Copy link
Member

chfast commented Jan 7, 2024

But in future it would be useful to mark whole gap there as skipped instead. If there is interest I would do it in another PR.

This would be very useful not to treat compile-time unreachable code as uncovered. Can the skipped code be marked separately in the reports?

@hanickadot
Copy link
Contributor Author

Yes, and it will be a bit bigger change. This is currently my biggest change yet :) But I want to do it as next. This fix's intention is to make the source location of regions properly done.

@hanickadot hanickadot force-pushed the main-coverage branch 4 times, most recently from c227189 to 413517b Compare January 8, 2024 10:56
@hanickadot
Copy link
Contributor Author

hanickadot commented Jan 8, 2024

Added some tests. And also pinging @ornata for review.

@ornata ornata self-requested a review January 9, 2024 03:46
Copy link

@ornata ornata left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added some comments, mostly nits on the test.

@ornata
Copy link

ornata commented Jan 9, 2024

LGTM

@hanickadot hanickadot requested a review from cor3ntin January 9, 2024 07:02
Copy link
Contributor

@cor3ntin cor3ntin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM
@hanickadot do you need me to merge that for you?

@hanickadot
Copy link
Contributor Author

yes please, I don't have merge rights

@cor3ntin
Copy link
Contributor

Oups, can you rebase?

@cor3ntin cor3ntin merged commit a26cc75 into llvm:main Jan 10, 2024
justinfargnoli pushed a commit to justinfargnoli/llvm-project that referenced this pull request Jan 28, 2024
…rt (llvm#77214)

Replace the discarded statement by an empty compound statement so we can keep track of the
whole source range we need to skip in coverage

Fixes llvm#54419
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:codegen IR generation bugs: mangling, exceptions, etc. clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category coverage
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants