[Coverage] Discard deferred region in closing if-else
authorVedant Kumar <vsk@apple.com>
Tue, 17 Oct 2017 07:47:39 +0000 (07:47 +0000)
committerVedant Kumar <vsk@apple.com>
Tue, 17 Oct 2017 07:47:39 +0000 (07:47 +0000)
A trailing deferred region isn't necessary in a function that ends with
this pattern:

  ...
  else {
    ...
    return;
  }

Special-case this pattern so that the closing curly brace of the
function isn't marked as uncovered. This issue came up in PR34962.

llvm-svn: 315982

clang/lib/CodeGen/CoverageMappingGen.cpp
clang/test/CoverageMapping/deferred-region.cpp

index 15c8194..08b8c2e 100644 (file)
@@ -758,6 +758,22 @@ struct CounterCoverageMappingBuilder
     handleFileExit(getEnd(S));
   }
 
+  /// Determine whether the final deferred region emitted in \p Body should be
+  /// discarded.
+  static bool discardFinalDeferredRegionInDecl(Stmt *Body) {
+    if (auto *CS = dyn_cast<CompoundStmt>(Body)) {
+      Stmt *LastStmt = CS->body_back();
+      if (auto *IfElse = dyn_cast<IfStmt>(LastStmt)) {
+        if (auto *Else = dyn_cast_or_null<CompoundStmt>(IfElse->getElse()))
+          LastStmt = Else->body_back();
+        else
+          LastStmt = IfElse->getElse();
+      }
+      return dyn_cast_or_null<ReturnStmt>(LastStmt);
+    }
+    return false;
+  }
+
   void VisitDecl(const Decl *D) {
     assert(!DeferredRegion && "Deferred region never completed");
 
@@ -770,14 +786,14 @@ struct CounterCoverageMappingBuilder
     Counter ExitCount = propagateCounts(getRegionCounter(Body), Body);
     assert(RegionStack.empty() && "Regions entered but never exited");
 
-    // Special case: if the last statement is a return, throw away the
-    // deferred region. This allows the closing brace to have a count.
-    if (auto *CS = dyn_cast_or_null<CompoundStmt>(Body))
-      if (dyn_cast_or_null<ReturnStmt>(CS->body_back()))
+    if (DeferredRegion) {
+      // Complete (or discard) any deferred regions introduced by the last
+      // statement.
+      if (discardFinalDeferredRegionInDecl(Body))
         DeferredRegion = None;
-
-    // Complete any deferred regions introduced by the last statement.
-    popRegions(completeDeferred(ExitCount, getEnd(Body)));
+      else
+        popRegions(completeDeferred(ExitCount, getEnd(Body)));
+    }
   }
 
   void VisitReturnStmt(const ReturnStmt *S) {
index 743b635..3504588 100644 (file)
@@ -31,11 +31,28 @@ void baz() { // CHECK: [[@LINE]]:12 -> [[@LINE+2]]:2
 // CHECK-LABEL: _Z3mazv:
 void maz() {
   if (true)
-    return; // CHECK: Gap,File 0, [[@LINE]]:11 -> 36:3 = (#0 - #1)
+    return; // CHECK: Gap,File 0, [[@LINE]]:11 -> [[@LINE+2]]:3 = (#0 - #1)
 
   return; // CHECK-NOT: Gap
 }
 
+// CHECK-LABEL: _Z4maazv:
+void maaz() {
+  if (true)
+    return; // CHECK: Gap,File 0, [[@LINE]]:11
+  else
+    return; // CHECK-NOT: Gap,File 0, [[@LINE]]
+}
+
+// CHECK-LABEL: _Z5maaazv:
+void maaaz() {
+  if (true) {
+    return;
+  } else {  // CHECK: Gap,File 0, [[@LINE]]:4 -> [[@LINE]]:10
+    return; // CHECK-NOT: Gap,File 0, [[@LINE]]
+  }
+}
+
 // CHECK-LABEL: _Z3bari:
 void bar(int x) {
   IF (x)
@@ -158,6 +175,9 @@ int main() {
   foo(1);
   fooo(0);
   fooo(1);
+  maz();
+  maaz();
+  maaaz();
   baz();
   bar(0);
   bar(1);