MaggieYi created this revision.
MaggieYi added reviewers: vsk, zequanwu.
MaggieYi added a project: clang.
Herald added a project: All.
MaggieYi requested review of this revision.
Herald added a subscriber: cfe-commits.

In the current coverage mapping implementation, we terminate the current region 
and start a zero region when we hit a nonreturn function. However, for logical 
OR, the second operand is not executed if the first operand evaluates to true. 
If the nonreturn function is called in the right side of logical OR and the 
left side of logical OR is TRUE, we should not start a zero `GapRegionCounter`. 
This will also apply to `VisitAbstractConditionalOperator`.

The following issues are fixed by this patch:

1. https://github.com/llvm/llvm-project/issues/59030
2. https://github.com/llvm/llvm-project/issues/57388
3. https://github.com/llvm/llvm-project/issues/57481
4. https://github.com/llvm/llvm-project/issues/60701


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D144371

Files:
  clang/lib/CodeGen/CoverageMappingGen.cpp
  clang/test/CoverageMapping/terminate-statements.cpp

Index: clang/test/CoverageMapping/terminate-statements.cpp
===================================================================
--- clang/test/CoverageMapping/terminate-statements.cpp
+++ clang/test/CoverageMapping/terminate-statements.cpp
@@ -320,6 +320,30 @@
   included_func();
 }
 
+// CHECK-LABEL: _Z7ornoretv:
+void abort() __attribute__((noreturn));
+
+int ornoret(void) {
+  ( true || (abort(), 0) );  // CHECK: Gap,File 0, [[@LINE]]:28 -> [[@LINE+1]]:3 = #0
+  ( false || (abort(), 0) ); // CHECK: Gap,File 0, [[@LINE]]:29 -> [[@LINE+1]]:3 = 0
+  return 0;
+}
+
+// CHECK-LABEL: _Z17abstractcondnoretv:
+int abstractcondnoret(void) {
+  ( true ? void (0) : abort() );  // CHECK: Gap,File 0, [[@LINE]]:33 -> [[@LINE+1]]:3 = #1
+  ( false ? void (0) : abort() ); // CHECK: Gap,File 0, [[@LINE]]:34 -> [[@LINE+1]]:3 = #2
+  return 0;
+}
+
+// CHECK-LABEL: _Z13elsecondnoretv:
+int elsecondnoret(void) {
+  if (true) {} else {
+    true ? void (0) : abort();
+  } // CHECK: Gap,File 0, [[@LINE]]:4 -> [[@LINE+1]]:3 = (#1 + #2)
+  return 0;
+}
+
 int main() {
   foo(0);
   foo(1);
@@ -339,5 +363,8 @@
   while_loop();
   gotos();
   include();
+  ornoret();
+  abstractcondnoret();
+  elsecondnoret();
   return 0;
 }
Index: clang/lib/CodeGen/CoverageMappingGen.cpp
===================================================================
--- clang/lib/CodeGen/CoverageMappingGen.cpp
+++ clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -1466,6 +1466,7 @@
     Counter TrueCount = getRegionCounter(E);
 
     propagateCounts(ParentCount, E->getCond());
+    Counter OutCount;
 
     if (!isa<BinaryConditionalOperator>(E)) {
       // The 'then' count applies to the area immediately after the condition.
@@ -1475,12 +1476,18 @@
         fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), TrueCount);
 
       extendRegion(E->getTrueExpr());
-      propagateCounts(TrueCount, E->getTrueExpr());
+      OutCount = propagateCounts(TrueCount, E->getTrueExpr());
     }
 
     extendRegion(E->getFalseExpr());
-    propagateCounts(subtractCounters(ParentCount, TrueCount),
-                    E->getFalseExpr());
+    OutCount = addCounters(
+        OutCount, propagateCounts(subtractCounters(ParentCount, TrueCount),
+                                  E->getFalseExpr()));
+
+    if (OutCount != ParentCount) {
+      pushRegion(OutCount);
+      GapRegionCounter = OutCount;
+    }
 
     // Create Branch Region around condition.
     createBranchRegion(E->getCond(), TrueCount,
@@ -1514,9 +1521,19 @@
                        subtractCounters(RHSExecCnt, RHSTrueCnt));
   }
 
+  // Determine whether the right side of OR operation need to be visited.
+  bool shouldVisitRHS(const Expr *LHS) {
+    bool LHSIsTrue = false;
+    bool LHSIsConst = false;
+    if (!LHS->isValueDependent())
+      LHSIsConst = LHS->EvaluateAsBooleanCondition(
+          LHSIsTrue, CVM.getCodeGenModule().getContext());
+    return !LHSIsConst || (LHSIsConst && !LHSIsTrue);
+  }
+
   void VisitBinLOr(const BinaryOperator *E) {
     extendRegion(E->getLHS());
-    propagateCounts(getRegion().getCounter(), E->getLHS());
+    Counter OutCount = propagateCounts(getRegion().getCounter(), E->getLHS());
     handleFileExit(getEnd(E->getLHS()));
 
     // Counter tracks the right hand side of a logical or operator.
@@ -1529,6 +1546,10 @@
     // Extract the RHS's "False" Instance Counter.
     Counter RHSFalseCnt = getRegionCounter(E->getRHS());
 
+    if (!shouldVisitRHS(E->getLHS())) {
+      GapRegionCounter = OutCount;
+    }
+
     // Extract the Parent Region Counter.
     Counter ParentCnt = getRegion().getCounter();
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to