diff --git a/gcc/testsuite/gdc.dg/gcov-1.d b/gcc/testsuite/gdc.dg/gcov-1.d
new file mode 100644
index 00000000000..0bc8e30b438
--- /dev/null
+++ b/gcc/testsuite/gdc.dg/gcov-1.d
@@ -0,0 +1,1712 @@
+/* { dg-options "-fcondition-coverage -ftest-coverage" } */
+/* { dg-do run { target native } } */
+
+/* Some side effect to stop branches from being pruned.  */
+int x = 0;
+
+int id  (int x) { return  x; }
+int inv (int x) { return !x; }
+
+/* || works.  */
+void
+mcdc001a (int a, int b)
+{
+    if (a || b) /* conditions(1/4) true(0) false(0 1) */
+		/* conditions(end) */
+	x = 1;
+    else
+	x = 2;
+}
+
+void
+mcdc001b (int a, int b)
+{
+    if (a || b) /* conditions(3/4) true(0) */
+		/* conditions(end) */
+	x = 1;
+    else
+	x = 2;
+}
+
+void
+mcdc001c (int a, int b)
+{
+    if (a || b) /* conditions(4/4) */
+	x = 1;
+    else
+	x = 2;
+}
+
+void
+mcdc001d (int a, int b, int c)
+{
+    if (a || b || c) /* conditions(2/6) false(0 1 2) true(2) */
+		     /* conditions(end) */
+	x = 1;
+}
+
+/* && works */
+void
+mcdc002a (int a, int b)
+{
+    if (a && b) /* conditions(1/4) true(0 1) false(0) */
+		/* conditions(end) */
+	x = 1;
+    else
+	x = 2;
+}
+
+void
+mcdc002b (int a, int b)
+{
+    if (a && b) /* conditions(3/4) false(0) */
+		/* conditions(end) */
+	x = 1;
+    else
+	x = 2;
+}
+
+void
+mcdc002c (int a, int b)
+{
+    if (a && b) /* conditions(4/4) */
+	x = 1;
+    else
+	x = 2;
+}
+
+void
+mcdc002d (int a, int b, int c)
+{
+    if (a && b && c) /* conditions(4/6) false(0 2) */
+		     /* conditions(end) */
+	x = 1;
+}
+
+/* Negation works.  */
+void
+mcdc003a (int a, int b)
+{
+    if (!a || !b) /* conditions(2/4) false(0 1) */
+		  /* conditions(end) */
+	x = 1;
+    else
+	x = 2;
+}
+
+/* Single conditionals with and without else.  */
+void
+mcdc004a (int a)
+{
+    if (a) /* conditions(1/2) true(0) */
+	   /* conditions(end) */
+	x = 1;
+    else
+	x = 2;
+}
+
+void
+mcdc004b (int a)
+{
+    if (a) /* conditions(2/2) */
+	x = 1;
+    else
+	x = 2;
+}
+
+void
+mcdc004c (int a)
+{
+    if (a) /* conditions(1/2) false(0) */
+	   /* conditions(end) */
+	x = 1;
+}
+
+void
+mcdc004d (int a, int b, int c)
+{
+    if (a)  /* conditions(2/2) */
+    {
+	if (b || c) /* conditions(1/4) true(1) false(0 1) */
+	    x = a + b + c;
+    }
+}
+
+void
+mcdc004e (int a, int b, int c)
+{
+    if (a)  /* conditions(2/2) */
+    {
+	if (b || c) /* conditions(1/4) true(1) false(0 1) */
+		    /* conditions(end) */
+	    x = a + b + c;
+    }
+    else
+    {
+	x = c;
+    }
+}
+
+void
+mcdc004f (int a, int b, int c)
+{
+    if (a)  /* conditions(1/2) false(0) */
+	    /* conditions(end) */
+    {
+	x = 1;
+    }
+    else if (b) /* conditions(0/2) true(0) false(0) */
+		/* conditions(end) */
+    {
+	x = 2;
+	if (c)  /* conditions(0/2) true(0) false(0) */
+		/* conditions(end) */
+	    x = 3;
+    }
+}
+
+/* Mixing && and || works.  */
+void
+mcdc005a (int a, int b, int c)
+{
+    if ((a && b) || c) /* conditions(1/6) true(0 1) false(0 1 2) */
+		       /* conditions(end) */
+	x = 1;
+    else
+	x = 2;
+}
+
+void
+mcdc005b (int a, int b, int c, int d)
+{
+    /* This is where masking MC/DC gets unintuitive:
+
+       1 1 0 0 => covers 1 (d = 0) as && 0 masks everything to the left
+       1 0 0 0 => covers 2 (b = 0, c = 0) as (a && 0) masks a and d is never
+       evaluated. */
+    if ((a && (b || c)) && d) /* conditions(3/8) true(0 1 2 3) false(0) */
+			      /* conditions(end) */
+	x = 1;
+    else
+	x = 2;
+}
+
+void
+mcdc005c (int a, int b, int c, int d)
+{
+    if (a || (b && c) || d) /* conditions(2/8) true(0 3) false(0 1 2 3) */
+			    /* conditions(end) */
+        x = a + b + c + d;
+}
+
+void
+mcdc005d (int a, int b, int c, int d)
+{
+    /* This test is quite significant - it has a single input
+       (1, 0, 0, 0) and tests specifically for when a multi-term left operand
+       is masked. d = 0 should mask a || b and for the input there are no other
+       sources for masking a (since b = 0). */
+    if ((a || b) && (c || d)) /* conditions(2/8) true(0 1 2 3) false(0 1) */
+			      /* conditions(end) */
+	x = a + b;
+    else
+	x = c + d;
+}
+
+/* Mixing in constants kills the decision removes the term outright.  */
+void
+mcdc005e (int a, int b)
+{
+  x += 0 && a;
+  x += a && 1;
+  x += 0 && a && b;
+  x += a && 1 && b; /* conditions(4/4) */
+  x += a && b && 0;
+  x += 0 && 1;
+  x += 1 && a;
+  x += a && 0;
+  x += 1 || a;
+  x += a || 0;
+  x += 1 || a || b;
+  x += a || 0 || b; /* conditions(4/4) */
+  x += a || b || 1;
+  x += 1 || 0;
+  x += 0 || a;
+  x += a || 1;
+}
+
+/* Nested conditionals.  */
+void
+mcdc006a (int a, int b, int c, int d, int e)
+{
+    if (a) /* conditions(2/2) */
+    {
+	if (b && c) /* conditions(3/4) false(1) */
+		    /* conditions(end) */
+	    x = 1;
+	else
+	    x = 2;
+    }
+    else
+    {
+	if (c || d) /* conditions(2/4) true(0 1) */
+		    /* conditions(end) */
+	    x = 3;
+	else
+	    x = 4;
+    }
+}
+
+void
+mcdc006b (int a, int b, int c)
+{
+    if (a) /* conditions(2/2) */
+	if (b) /* conditions(2/2) */
+	    if (c) /* conditions(2/2) */
+		x = a + b + c;
+}
+
+void
+mcdc006c (int a, int b, int c)
+{
+    if (a) /* conditions(2/2) */
+    {
+	if (b) /*conditions(2/2) */
+	{
+	    if (c) /* conditions(2/2) */
+	    {
+		x = a + b + c;
+	    }
+	}
+	else
+	{
+	    x = b;
+	}
+    }
+    else
+    {
+	x = a;
+    }
+}
+
+void
+mcdc006d (int a, int b, int c)
+{
+    if (a)	/* conditions(1/2) false(0) */
+		/* conditions(end) */
+    {
+	if (b)	/* conditions(1/2) true(0) */
+		/* conditions(end) */
+	    x = a + b;
+	if (c)	/* conditions(2/2) */
+		/* conditions(end) */
+	    x = a + b;
+    }
+}
+
+void
+mcdc006e (int a, int b, int c, int d)
+{
+    if ((a || b || c) && id (d)) /* conditions(4/8) true(0 1 2 3) false() */
+				 /* conditions(end) */
+	x = 1;
+}
+
+/* else/if.  */
+void
+mcdc007a (int a, int b, int c, int d)
+{
+    if (a) /* conditions(2/2) */
+    {
+	if (b) /* conditions(1/2) true(0) */
+	       /* conditions(end) */
+	    x = 1;
+	else
+	    x = 2;
+    }
+    else if (c) /* conditions(2/2) */
+    {
+	if (d) /* conditions(1/2) true(0) */
+	       /* conditions(end) */
+	    x = 3;
+	else
+	    x = 4;
+    }
+}
+
+void
+mcdc007b (int a, int b, int c)
+{
+    goto begin;
+then:
+    x = 1;
+    return;
+begin:
+    if (a)	/* conditions(2/2) */
+	goto then;
+    else if (b)	/* conditions(2/2) */
+	goto then;
+    else if (c) /* conditions(1/2) true(0) */
+	goto then;
+}
+
+void
+mcdc007c (int a, int b, int c)
+{
+    goto begin;
+then1:
+    x = 1;
+    return;
+then2:
+    x = 1;
+    return;
+then3:
+    x = 1;
+    return;
+begin:
+    if (a) /* conditions(2/2) */
+	goto then1;
+    else if (b) /* conditions(2/2) */
+	goto then2;
+    else if (c) /* conditions(1/2) true(0) */
+		/* conditions(end) */
+	goto then3;
+}
+
+void
+noop () {}
+
+int
+mcdc007d (int a, int b, int c, int d, int e)
+{
+    noop ();
+    if (a)  /* conditions(1/2) true(0) */
+	    /* conditions(end) */
+    {
+	if (b || c) /* conditions(0/4) true(0 1) false(0 1) */
+		    /* conditions(end) */
+	    x = 2;
+	if (d)	/* conditions(0/2) true(0) false(0) */
+		/* conditions(end) */
+	    return 1;
+    }
+    if (e)  /* conditions(1/2) false(0) */
+	    /* conditions(end) */
+	return 0;
+
+    return 2;
+}
+
+/* while loop.  */
+void
+mcdc008a (int a)
+{
+    while (a < 10) /* conditions(2/2) */
+	x = a++;
+}
+
+void
+mcdc008b (int a)
+{
+    /* gdc inverts this check.  */
+    while (a > 10) /* conditions(1/2) false(0) */
+		   /* conditions(end) */
+	x = a--;
+}
+
+void
+mcdc008c (int a)
+{
+    // should work, even with no body
+    while (a) /* conditions(2/2) */
+	break;
+}
+
+void
+mcdc008d (int a, int b, int c, int d)
+{
+    /* Multi-term loop conditional.  */
+    while ((a && (b || c)) && d) /* conditions(8/8) */
+	a = b = c = d = 0;
+}
+
+void
+mcdc009a (int a, int b)
+{
+    while (a > 0 && b > 0) /* conditions(3/4) true(1) */
+			   /* conditions(end) */
+	x = a--;
+}
+
+void
+mcdc009b (int a, int b)
+{
+    while (a-- > 0 && b) {} /* conditions(2/4) false(0 1) */
+			    /* conditions(end) */
+}
+
+/* for loop.  */
+void
+mcdc010a (int a, int b)
+{
+    for (int i = 0; i < b; i++) /* conditions(2/2) */
+    {
+	if (a < b) /* conditions(2/2) */
+	    x = 1;
+	else
+	    x = a += 2;
+    }
+}
+
+void
+mcdc010b ()
+{
+    for (int a = 0; a <= 1; ++a) /* conditions(2/2) */
+    {
+	x = a;
+    }
+}
+
+int
+mcdc010c (int a, int b, int c)
+{
+    for (;a || b || c;) /* conditions(4/6) false(0 2) */
+			/* conditions(end) */
+	return 1;
+    return 0;
+}
+
+
+int always (int x) { return 1; }
+
+/* No-condition infinite loops.  */
+void
+mcdc010d (int a)
+{
+    for (;;)
+    {
+	if (always(a)) /* conditions(1/2) false(0) */
+		       /* conditions(end) */
+	{
+	    x = a;
+	    break;
+	}
+	x += a + 1;
+    }
+}
+
+/* conditionals without control flow constructs work */
+void
+mcdc011a (int a, int b, int c)
+{
+    x = (a && b) || c; /* conditions(5/6) false(1) */
+		       /* conditions(end) */
+}
+
+/* Sequential expressions are handled independently.  */
+void
+mcdc012a (int a, int b, int c)
+{
+    if (a || b) /* conditions(3/4) true(0) */
+		/* conditions(end) */
+	x = 1;
+    else
+	x = 2;
+
+    if (c) /* conditions(2/2) */
+	x = 1;
+}
+
+/* Cannot ever satisfy (masking) MC/DC, even with all input combinations,
+   because not all variables independently affect the decision.  */
+void
+mcdc013a (int a, int b, int c)
+{
+    /* Specification: (a && b) || c
+       The implementation does not match the specification.  This has branch
+       coverage, but not MC/DC. */
+    if ((a && !c) || c) /* conditions(5/6) false(1) */
+			/* conditions(end) */
+	x = 1;
+    else
+	x = 2;
+}
+
+void
+mcdc014a ()
+{
+    int[64] conds;
+    /* conditions(64/128) true(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63) */
+    x = conds[ 0] || conds[ 1] || conds[ 2] || conds[ 3] || conds[ 4] ||
+	conds[ 5] || conds[ 6] || conds[ 7] || conds[ 8] || conds[ 9] ||
+	conds[10] || conds[11] || conds[12] || conds[13] || conds[14] ||
+	conds[15] || conds[16] || conds[17] || conds[18] || conds[19] ||
+	conds[20] || conds[21] || conds[22] || conds[23] || conds[24] ||
+	conds[25] || conds[26] || conds[27] || conds[28] || conds[29] ||
+	conds[30] || conds[31] || conds[32] || conds[33] || conds[34] ||
+	conds[35] || conds[36] || conds[37] || conds[38] || conds[39] ||
+	conds[40] || conds[41] || conds[42] || conds[43] || conds[44] ||
+	conds[45] || conds[46] || conds[47] || conds[48] || conds[49] ||
+	conds[50] || conds[51] || conds[52] || conds[53] || conds[54] ||
+	conds[55] || conds[56] || conds[57] || conds[58] || conds[59] ||
+	conds[60] || conds[61] || conds[62] || conds[63]
+	;  /* conditions(end) */
+}
+
+/* Early returns.  */
+void
+mcdc015a (int a, int b)
+{
+    if (a) /* conditions(2/2) */
+	return;
+
+    if (b) /* conditions(1/2) true(0) */
+	   /* conditions(end) */
+	x = 1;
+}
+
+void
+mcdc015b (int a, int b)
+{
+    for (int i = 5; i > a; i--) /* conditions(2/2) */
+    {
+	if (i == b) /* conditions(2/2) */
+	    return;
+	x = i;
+    }
+}
+
+void
+mcdc015c (int a, int b)
+{
+    for (int i = 5; i > a; i--) /* conditions(2/2) */
+    {
+	if (i == b) /* conditions(2/2) */
+	{
+	    x = 0;
+	    return;
+	}
+	else
+	{
+	    x = 1;
+	    return;
+	}
+
+	x = i;
+    }
+}
+
+/* Early returns, gotos.  */
+void
+mcdc015d (int a, int b, int c)
+{
+    if (a) return;  /* conditions(1/2) false(0) */
+		    /* conditions(end) */
+    if (id (b)) return; /* conditions(0/2) true(0) false(0) */
+			/* conditions(end) */
+    if (id (c)) return; /* conditions(0/2) true(0) false(0) */
+			/* conditions(end) */
+}
+
+
+/* Check nested loops.  */
+void
+mcdc016a (int a, int b)
+{
+    for (int i = 0; i < a; i++) /* conditions(2/2) */
+	for (int k = 0; k < b; k++) /* conditions(2/2) */
+	    x = i + k;
+}
+
+void
+mcdc016b (int a, int b)
+{
+    for (int i = 0; i < a; i++) /* conditions(2/2) */
+    {
+	if (a > 5) /* conditions(2/2) */
+	    break;
+
+	for (int k = 0; k < b; k++) /* conditions(2/2) */
+	    x = i + k;
+    }
+}
+
+void
+mcdc016c (int a, int b)
+{
+    for (int i = 0; i < a; i++) /* conditions(2/2) */
+    {
+	if (a > 5) /* conditions(1/2) true(0) */
+		   /* conditions(end) */
+	    return;
+
+	for (int k = 0; k < b; k++) /* conditions(2/2) */
+	    x = i + k;
+    }
+}
+
+void
+mcdc016d (int a, int b)
+{
+    for (int i = 0; i < a; i++) /* conditions(2/2) */
+    {
+	for (int k = 0; k < 5; k++) /* conditions(2/2) */
+	{
+	    if (b > 5) /* conditions(1/2) true(0) */
+		       /* conditions(end) */
+		return;
+	    x = i + k;
+	}
+
+    }
+}
+
+/* do-while loops.  */
+void
+mcdc017a (int a)
+{
+    do
+    {
+	/* conditions(2/2) */
+	a--; 
+    } while (a > 0);
+}
+
+void
+mcdc017b (int a, int b)
+{
+    do /* conditions(2/2) */
+    {
+	/* This call is important; it can add more nodes to the body in the
+	   CFG, which changes how close exits and breaks are to the loop
+	   conditional.  */
+	noop ();
+	a--;
+	if (b) /* conditions(2/2) */
+	    break;
+    } while (a > 0);
+}
+
+void
+mcdc017c (int a, int b)
+{
+    int left = 0;
+    int right = 0;
+    int n = a + b;
+    do
+    {
+	if (a) /* conditions(1/2) false(0) */
+	       /* conditions(end) */
+	{
+	    left = a > left ? b : left; /* conditions(2/2) */
+	}
+	if (b) /* conditions(1/2) false(0) */
+	       /* conditions(end) */
+	{
+	    right = b > right ? a : right; /* conditions(2/2) */
+	}
+    } while (n-- > 0); /* conditions(2/2) */
+}
+
+void
+mcdc017d (int a, int b, int c)
+{
+    do
+    {
+	a--;  /* conditions(0/6) true(0 1 2) false(0 1 2) */
+	      /* conditions(end) */
+    } while (a > 0 && b && c);
+}
+
+/* Collection of odd cases lifted-and-adapted from real-world code.  */
+int
+mcdc018a (int a, int b, int c, int d, int e, int f, int g, int len)
+{
+    int n;
+    /* adapted from zlib/gz_read */
+    do
+    {
+	n = -1;
+	if (n > len) /* conditions(2/2) */
+	    n = len;
+
+	if (b) /* conditions(2/2) */
+	{
+	    if (b < 5) /* conditions(2/2) */
+		x = 1;
+	    noop();
+	}
+	else if (c && d) /* conditions(3/4) false(1) */
+			 /* conditions(end) */
+	{
+	    x = 2;
+	    break;
+	}
+	else if (e || f) /* conditions(2/4) false(0 1) */
+			 /* conditions(end) */
+	{
+	    if (id(g)) /* conditions(2/2) */
+		return 0;
+	    continue;
+	}
+    } while (a-- > 0); /* conditions(2/2) */
+
+    return 1;
+}
+
+void
+mcdc018b (int a, int b, int c)
+{
+    int n;
+    while (a) /* conditions(2/2) */
+    {
+	/* else block does not make a difference for the problem, but ensures
+	   loop termination. */
+	if (b) /* conditions(2/2) */
+	    n = c ? 0 : 0; // does not show up in CFG (embedded in the block)
+	else
+	    n = 0;
+	a = n;
+    }
+}
+
+/* Adapted from zlib/compress2.  */
+void
+mcdc018c (int a, int b)
+{
+    int err;
+    do
+    {
+	a = inv (a);
+	err = a; /* conditions(1/2) false(0) */
+		 /* conditions(end) */
+    } while (err);
+
+    a = id (a);
+    if (a) /* conditions(1/2) true(0) */
+	   /* conditions(end) */
+	x *= a + 1;
+}
+
+/* Too many conditions, coverage gives up. */
+void
+mcdc019a ()
+{
+    /* This will warn and needs a pragma warning suppression (or similar)
+       mechanism to not cause trigger a test failure from the warning.
+    int[65] conds;
+    x = conds[ 0] || conds[ 1] || conds[ 2] || conds[ 3] || conds[ 4] ||
+	conds[ 5] || conds[ 6] || conds[ 7] || conds[ 8] || conds[ 9] ||
+	conds[10] || conds[11] || conds[12] || conds[13] || conds[14] ||
+	conds[15] || conds[16] || conds[17] || conds[18] || conds[19] ||
+	conds[20] || conds[21] || conds[22] || conds[23] || conds[24] ||
+	conds[25] || conds[26] || conds[27] || conds[28] || conds[29] ||
+	conds[30] || conds[31] || conds[32] || conds[33] || conds[34] ||
+	conds[35] || conds[36] || conds[37] || conds[38] || conds[39] ||
+	conds[40] || conds[41] || conds[42] || conds[43] || conds[44] ||
+	conds[45] || conds[46] || conds[47] || conds[48] || conds[49] ||
+	conds[50] || conds[51] || conds[52] || conds[53] || conds[54] ||
+	conds[55] || conds[56] || conds[57] || conds[58] || conds[59] ||
+	conds[60] || conds[61] || conds[62] || conds[63] || conds[64]
+	;
+    */
+}
+
+/* Ternary.  */
+void
+mcdc020a (int a)
+{
+    /* In C this is reduced to
+       _1 = argc != 0;
+       e = (int) _1;
+       but in D the branches are preserved.  */
+    x = a ? 1 : 0; /* conditions(2/2) */
+    x = a ? 2 : 1; /* conditions(2/2) */
+}
+
+void
+mcdc020b (int a, int b)
+{
+    x = (a || b) ? 1 : 0; /* conditions(3/4) true(1) */
+			  /* conditions(end) */
+}
+
+void
+mcdc020c (int a, int b)
+{
+    x = a ? 0	/* conditions(2/2) */
+	: b ? 1 /* conditions(1/2) false(0) */
+		/* conditions(end) */
+	: 2;    
+}
+
+int
+mcdc020d (int b, int c, int d, int e, int f)
+{
+    return ((b ? c : d) && e && f); /* conditions(7/10) true(2) false(3 4) */
+				    /* conditions(end) */
+}
+
+/* Infinite loop (no exit-edge), this should not be called, but it should
+   compile fine.  */
+void
+mcdc021a ()
+{
+    while (1) {}
+}
+
+/* If edges are not properly contracted the a && id (b) will be interpreted as
+   two independent expressions. */
+void
+mcdc021d (int a, int b, int c, int d)
+{
+    if (a && id (b)) /* conditions(1/4) true(0 1) false(0) */
+		     /* conditions(end) */
+	x = 1;
+    else if (c && id (d)) /* conditions(1/4) true(0 1) false(0) */
+			  /* conditions(end) */
+	x = 2;
+    else
+	x = 3;
+}
+
+/* Adapted from linux arch/x86/tools/relocs.c
+   With poor edge contracting this became an infinite loop. */
+void
+mcdc022a (int a, int b)
+{
+    for (int i = 0; i < 5; i++) /* conditions(2/2) */
+    {
+	x = i;
+	for (int j = i; j < 5; j++) /* conditions(2/2) */
+	{
+	    if (id (id (a)) || id (b)) /* conditions(3/4) true(0) */
+				       /* conditions(end) */
+		continue;
+	    b = inv(b);
+	}
+    }
+}
+
+int
+mcdc022b (int a)
+{
+    int devt;
+    if (a) /* conditions(2/2) */
+    {
+	x = a * 2;
+	if (x != a / 10 || x != a % 10) /* conditions(1/4) true(1) false(0 1) */
+					/* conditions(end) */
+	    return 0;
+    } else {
+	devt = id (a);
+	if (devt) /* conditions(1/2) true(0) */
+		  /* conditions(end) */
+	    return 0;
+    }
+
+    return devt;
+}
+
+/* Adapted from linux arch/x86/events/intel/ds.c
+
+   It broken sorting so that the entry block was not the first node after
+   sorting. */
+void
+mcdc022c (int a)
+{
+    if (!a) /* conditions(2/2) */
+	return;
+
+    for (int i = 0; i < 5; i++) /* conditions(2/2) */
+    {
+	if (id (a + i) || inv (a - 1)) /* conditions(1/4) false(0 1) true(1) */
+				       /* conditions(end) */
+	    x = a + i;
+	if (inv (a)) /* conditions(1/2) true(0) */
+		     /* conditions(end) */
+	    break;
+    }
+}
+
+void
+mcdc022d (int a)
+{
+    int i;
+    for (i = 0; i < id (a); i++) /* conditions(1/2) true(0) */
+    {
+	if (!inv (a)) /* conditions(1/2) false(0)*/
+		      /* conditions(end) */
+	    break;
+    }
+
+    if (i < a) /* conditions(1/2) false(0) */
+	       /* conditions(end) */
+	x = a + 1;
+}
+
+/* Adapted from openssl-3.0.1/crypto/cmp/cmp_msg.c ossl_cmp_error_new ().  */
+void
+mcdc022e (int a, int b, int c, int d)
+{
+    if (a || b) /* conditions(1/4) true(0) false(0 1) */
+		/* conditions(end) */
+    {
+	if (always (c)) /* conditions(1/2) false(0) */
+			/* conditions(end) */
+	    goto err;
+	d++;
+    }
+
+    if (d)  /* conditions(0/2) true(0) false(0) */
+	    /* conditions(end) */
+	goto err;
+    return;
+
+err:
+    noop ();
+}
+
+/* 023 specifically tests that masking works correctly, which gets complicated
+   fast with a mix of operators and deep subexpressions.  These tests violates
+   the style guide slightly to emphasize the nesting.  They all share the same
+   implementation and only one input is given to each function to obtain clean
+   coverage results. */
+void
+mcdc023a (int a, int b, int c, int d, int e, int f, int g, int h, int i, int k,
+	  int l, int m, int n)
+{
+    // [a m n] = 0, [b, ...] = 1
+    // a is masked by b and the remaining terms should be short circuited
+    if (/* conditions(1/24) true(0 2 3 4 5 6 7 8 9 10 11) false(0 1 2 3 4 5 6 7 8 9 10 11) */
+	/* conditions(end) */
+	   (a || b)
+	|| (   ((c && d) || (e && (f || g) && h))
+	    && (k || l)
+	    && (m || n)))
+	x = a + b;
+    else
+	x = b + c;
+}
+
+void
+mcdc023b (int a, int b, int c, int d, int e, int f, int g, int h, int i, int k,
+	  int l, int m, int n)
+{
+    // [a b d h] = 0, [c, ...] = 1
+    // h = 0 => false but does not mask (a || b) or (c && d). d = 0 masks c.
+    if (/* conditions(4/24) true(0 1 2 3 4 5 6 7 8 9 10 11) false(2 4 5 6 8 9 10 11) */
+	/* conditions(end) */
+	   (a || b)
+	|| (   ((c && d) || (e && (f || g) && h))
+	    && (k || l)
+	    && (m || n)))
+	x = a + b;
+    else
+	x = b + c;
+}
+
+void
+mcdc023c (int a, int b, int c, int d, int e, int f, int g, int h, int i, int k,
+	  int l, int m, int n)
+{
+    /* [m n a b] = 0, [...] = 1
+       n,m = 0 should mask all other terms than a, b */
+    if (/* conditions(4/24) true(0 1 2 3 4 5 6 7 8 9 10 11) false(2 3 4 5 6 7 8 9) */
+	/* conditions(end) */
+	   (a || b)
+	|| (   ((c && d) || (e && (f || g) && h))
+	    && (k || l)
+	    && (m || n)))
+	x = a + b;
+    else
+	x = b + c;
+}
+
+void
+mcdc023d (int a, int b, int c, int d, int e, int f, int g, int h, int i, int k,
+	  int l, int m, int n)
+{
+    /* [a b] = 0, [h, ...] = 1
+       n,m = 0 should mask all other terms than a, b */
+    if (/* conditions(4/24) true(0 1 2 3 4 5 6 7 8 9 10 11) false(2 3 4 5 6 7 10 11) */
+	/* conditions(end) */
+	   (a || b)
+	|| (   ((c && d) || (e && (f || g) && h))
+	    && (k || l)
+	    && (m || n)))
+	x = a + b;
+    else
+	x = b + c;
+}
+
+void
+mcdc023e (int a, int b, int c, int d, int e, int f, int g, int h, int i, int k,
+	  int l, int m, int n)
+{
+    /* [a b d] = 0, [c h, ...] = 1
+       h = 1 should mask c, d, leave other terms intact.
+       If [k l m n] were false then h itself would be masked.
+       [a b] are masked as collateral by [m n]. */
+    if (/* conditions(5/24) true(0 1 2 3 6 9 11) false(0 1 2 3 4 5 6 7 8 9 10 11) */
+	/* conditions(end) */
+	   (a || b)
+	|| (   ((c && d) || (e && (f || g) && h))
+	    && (k || l)
+	    && (m || n)))
+	x = a + b;
+    else
+	x = b + c;
+}
+
+void
+mcdc023f (int a, int b, int c, int d, int e, int f, int g, int h, int i, int k,
+	  int l, int m, int n)
+{
+    /* [a b c f g] = 0, [e, ...] = 1
+       [f g] = 0 should mask e, leave [c d] intact. */
+    if (/* conditions(5/24) true(0 1 2 3 4 5 6 7 8 9 10 11) false(3 4 7 8 9 10 11) */
+	/* conditions(end) */
+	   (a || b)
+	|| (   ((c && d) || (e && (f || g) && h))
+	    && (k || l)
+	    && (m || n)))
+	x = a + b;
+    else
+	x = b + c;
+}
+
+void
+mcdc023g (int a, int b, int c, int d, int e, int f, int g, int h, int i, int k,
+	  int l, int m, int n)
+{
+    /* [a b d f g] = 0, [e c, ...] = 1
+       Same as 023f but with [c d] flipped so d masks c rather than c
+       short-circuits.  This should not be lost. */
+    if (/* conditions(5/24) true(0 1 2 3 4 5 6 7 8 9 10 11) false(2 4 7 8 9 10 11) */
+	/* conditions(end) */
+	   (a || b)
+	|| (   ((c && d) || (e && (f || g) && h))
+	    && (k || l)
+	    && (m || n)))
+	x = a + b;
+    else
+	x = b + c;
+}
+
+/* Gotos, return, labels can make odd graphs.  It is important that conditions
+   are assigned to the right expression, and that there are no miscounts.  In
+   these tests values may be re-used, as checking things like masking an
+   independence is done in other test cases and not so useful here.  */
+void
+mcdc024a (int a, int b)
+{
+    /* This is a reference implementation without the labels, which should not
+       alter behavior.  */
+    if (a && b) /* conditions(2/4) true(0 1) */
+		/* conditions(end) */
+    {
+	x = 1;
+    }
+    else
+    {
+	x = 2;
+    }
+
+    if (a || b) /* conditions(2/4) false(0 1) */
+		/* conditions(end) */
+    {
+	x = 1;
+    }
+    else
+    {
+	x = 2;
+    }
+}
+
+void
+mcdc024b (int a, int b)
+{
+    if (a && b) /* conditions(2/4) true(0 1) */
+		/* conditions(end) */
+    {
+label1:
+	x = 1;
+    }
+    else
+    {
+	x = 2;
+    }
+
+    if (a || b) /* conditions(2/4) false(0 1) */
+		/* conditions(end) */
+    {
+label2:
+	x = 1;
+    }
+    else
+    {
+	x = 2;
+    }
+}
+
+void
+mcdc024c (int a, int b)
+{
+
+    if (a && b) /* conditions(2/4) true(0 1) */
+		/* conditions(end) */
+    {
+	x = 1;
+    }
+    else
+    {
+label1:
+	x = 2;
+    }
+
+    if (a || b) /* conditions(2/4) false(0 1) */
+		/* conditions(end) */
+    {
+	x = 1;
+    }
+    else
+    {
+label2:
+	x = 2;
+    }
+}
+
+void
+mcdc024d (int a, int b)
+{
+    if (a && b) /* conditions(2/4) true(0 1) */
+		/* conditions(end) */
+    {
+label1:
+	x = 1;
+    }
+    else
+    {
+label2:
+	x = 2;
+    }
+
+    if (a || b) /* conditions(2/4) false(0 1) */
+		/* conditions(end) */
+    {
+label3:
+	x = 1;
+    }
+    else
+    {
+label4:
+	x = 2;
+    }
+}
+
+int
+mcdc024e (int a, int b, int c)
+{
+    /* Graphs can get complicated with the innermost returns and else-less if,
+       so we must make sure these conditions are counted correctly.  */
+    if (a)  /* conditions(1/2) true(0) */
+	    /* conditions(end) */
+    {
+	if (b)	/* conditions(0/2) true(0) false(0) */
+		/* conditions(end) */
+	{
+	    if (c)  /* conditions(0/2) true(0) false(0) */
+		    /* conditions(end) */
+		return 1;
+	    else
+		return 2;
+	}
+
+	if (a)	/* conditions(0/2) true(0) false(0) */
+		/* conditions(end) */
+	    return 3;
+    }
+
+    return 5;
+}
+
+/* Nested else-less ifs with inner returns needs to be counted right, which
+   puts some pressure on the expression isolation.  */
+int
+mcdc024f (int a, int b, int c)
+{
+    if (a)  /* conditions(1/2) true(0) */
+	    /* conditions(end) */
+    {
+	if (b)	/* conditions(0/2) true(0) false(0) */
+		/* conditions(end) */
+	{
+	    if (c)  /* conditions(0/2) true(0) false(0) */
+		    /* conditions(end) */
+	    {
+		if (a)	/* conditions(0/2) true(0) false(0) */
+			/* conditions(end) */
+		    return 1;
+		else
+		    return 2;
+	    }
+
+	    if (a)  /* conditions(0/2) true(0) false(0) */
+		    /* conditions(end) */
+		return 3;
+	}
+
+	if (b)	/* conditions(0/2) true(0) false(0) */
+		/* conditions(end) */
+	    return 4;
+    }
+    return 5;
+}
+
+int
+mcdc024g (int a, int b, int c)
+{
+    if (b)  /* conditions(1/2) true(0) */
+	    /* conditions(end) */
+	return 0;
+
+    if (a)  /* conditions(1/2) true(0) */
+	    /* conditions(end) */
+    {
+	if (b)	/* conditions(0/2) true(0) false(0) */
+		/* conditions(end) */
+	{
+	    b += 2;
+	    if (b & 0xFF)   /* conditions(0/2) true(0) false(0) */
+			    /* conditions(end) */
+		c++;
+
+	    return c;
+	}
+	c += 10;
+    }
+    return 1;
+}
+
+
+int
+mcdc024h (int a, int b, int c)
+{
+    if (b)  /* conditions(1/2) true(0) */
+	    /* conditions(end) */
+	goto inner;
+
+    if (a)  /* conditions(1/2) true(0) */
+	    /* conditions(end) */
+	++a;
+
+
+    if (a)  /* conditions(1/2) true(0) */
+	    /* conditions(end) */
+    {
+	if (b)	/* conditions(0/2) true(0) false(0) */
+		/* conditions(end) */
+	{
+inner:
+	    b += 2;
+	    if (b & 0xFF)   /* conditions(0/2) true(0) false(0) */
+			    /* conditions(end) */
+		c++;
+
+	    return c;
+	}
+	c += 10;
+    }
+    return 1;
+}
+
+int
+mcdc024i (int a, int b, int c)
+{
+fst:
+    b++;
+snd:
+    b++;
+
+    if (b > 10) /* conditions(2/2) */
+		/* conditions(end) */
+	goto end;
+
+    if (b < 5)  /* conditions(2/2) */
+		/* conditions(end) */
+	goto fst;
+    else
+	goto snd;
+
+end:
+    if (a)  /* conditions(1/2) true(0) */
+	    /* conditions(end) */
+	++a;
+
+
+    if (a)  /* conditions(1/2) true(0) */
+	    /* conditions(end) */
+    {
+	if (b)	/* conditions(0/2) true(0) false(0) */
+		/* conditions(end) */
+	{
+	    b += 2;
+	    if (b & 0xFF)   /* conditions(0/2) true(0) false(0) */
+			    /* conditions(end) */
+		c++;
+
+	    return c;
+	}
+	c += 10;
+    }
+    return 1;
+}
+
+/* Adapted from alsa-lib 1.2.8 src/control/control.c.  If two expressions share
+   an outcome with bypass nodes they would be marked twice.  */
+int
+mcdc025a (int a, int b, int c)
+{
+    int err;
+    if (id (a)) /* conditions(1/2) true(0) */
+		/* conditions(end) */
+    {
+	if (b)	/* conditions(0/2) true(0) false(0) */
+		/* conditions(end) */
+	    return -1;
+    }
+    else
+    {
+	err = id (c);
+	if (err > 0) /* conditions(1/2) false(0) */
+		     /* conditions(end) */
+	    return err;
+    }
+    err = id (a);
+    return err;
+}
+
+/* Boolean expressions in function call parameters.  These tests are all built
+   with a reference expression which should behave the same as the function
+   call versions.  */
+int
+mcdc026a (int a, int b, int c, int d, int e)
+{
+    int cad = c && d; /* conditions(4/4) */
+		      /* conditions(end) */
+    int x = a && b && cad && e;		/* conditions(5/8) false(0 1 3) */
+					/* conditions(end) */
+    int y = a && b && id (c && d) && e;	/* conditions(5/8; 4/4) false(0 1 3;;) */
+					/* conditions(end) */
+    return x + y;
+}
+
+int
+mcdc026b (int a, int b, int c, int d, int e)
+{
+    int dae = d && e; /* conditions(3/4) false(1) */
+		      /* conditions(end) */
+    int x = a && b && c && dae;		/* conditions(6/8) false(0 1) */
+    int y = a && b && c && id (d && e);	/* conditions(6/8; 3/4) false(0 1; 1) */
+					/* conditions(end) */
+    return x + y;
+}
+
+int
+mcdc026c (int a, int b, int c, int d, int e)
+{
+    int cod = c || d;	/* conditions(3/4) true(1) */
+			/* conditions(end) */
+    int x = a && b && cod && e;		/* conditions(5/8) false(0 1 3) */
+    int y = a && b && id (c || d) && e;	/* conditions(5/8; 3/4) true(;1) false(0 1 3;) */
+					/* conditions(end) */
+    return x+y;
+}
+
+int
+mcdc026d (int a, int b, int c, int d, int e)
+{
+    int aab = a && b; /* conditions(2/4) false(0 1) */
+		      /* conditions(end) */
+    int cod = c || d; /* conditions(3/4) true(1) */
+		      /* conditions(end) */
+    int x = aab && cod && e; /* conditions(4/6) false(0 2) */
+			     /* conditions(end) */
+    int y = id (a && b) && id (c || d) && e; /* conditions(2/4;4/6;3/4) true(;;1) false(0 1;0 2;;) */
+					     /* conditions(end) */
+    return x + y;
+}
+
+int
+mcdc026e (int a, int b, int c, int d, int e)
+{
+    int cod = c || d; /* conditions(3/4) true(1) */
+		      /* conditions(end) */
+    int dae = d && e; /* conditions(3/4) false(1) */
+		      /* conditions(end) */
+    int aacod = a && cod; /* conditions(3/4) false(0)*/
+			  /* conditions(end) */
+    int x = aacod && dae; /* conditions(4/4) */
+			  /* conditions(end) */
+    int y = id (a && id (c || d)) && id (d && e); /* conditions(3/4; 3/4; 4/4; 3/4) true(;1;;) false(0;;;1) */
+						  /* conditions(end) */
+    return x + y;
+}
+
+void main ()
+{
+    mcdc001a (0, 1);
+
+    mcdc001b (0, 1);
+    mcdc001b (0, 0);
+
+    mcdc001c (0, 1);
+    mcdc001c (0, 0);
+    mcdc001c (1, 1);
+
+    mcdc001d (1, 1, 1);
+    mcdc001d (0, 1, 0);
+
+    mcdc002a (1, 0);
+
+    mcdc002b (1, 0);
+    mcdc002b (1, 1);
+
+    mcdc002c (0, 0);
+    mcdc002c (1, 1);
+    mcdc002c (1, 0);
+
+    mcdc002d (1, 1, 1);
+    mcdc002d (1, 0, 0);
+
+    mcdc003a (0, 0);
+    mcdc003a (1, 0);
+
+    mcdc004a (0);
+    mcdc004b (0);
+    mcdc004b (1);
+    mcdc004c (1);
+
+    mcdc004d (0, 0, 0);
+    mcdc004d (1, 1, 1);
+
+    mcdc004e (0, 0, 0);
+    mcdc004e (1, 1, 1);
+
+    mcdc004f (1, 1, 1);
+
+    mcdc005a (1, 0, 1);
+
+    mcdc005b (1, 1, 0, 0);
+    mcdc005b (1, 0, 0, 0);
+
+    mcdc005c (0, 1, 1, 0);
+
+    mcdc005d (1, 0, 0, 0);
+
+    mcdc005e (0, 0);
+    mcdc005e (0, 1);
+    mcdc005e (1, 0);
+    mcdc005e (1, 1);
+
+    mcdc006a (0, 0, 0, 0, 0);
+    mcdc006a (1, 0, 0, 0, 0);
+    mcdc006a (1, 1, 1, 0, 0);
+
+    mcdc006b (0, 0, 0);
+    mcdc006b (1, 0, 0);
+    mcdc006b (1, 1, 0);
+    mcdc006b (1, 1, 1);
+
+    mcdc006c (0, 0, 0);
+    mcdc006c (1, 0, 0);
+    mcdc006c (1, 1, 0);
+    mcdc006c (1, 1, 1);
+
+    mcdc006d (1, 0, 0);
+    mcdc006d (1, 0, 1);
+
+    mcdc006e (0, 0, 0, 0);
+    mcdc006e (0, 0, 1, 0);
+    mcdc006e (0, 1, 0, 0);
+
+    mcdc007a (0, 0, 0, 0);
+    mcdc007a (1, 0, 0, 0);
+    mcdc007a (0, 0, 1, 0);
+
+    mcdc007b (0, 0, 0);
+    mcdc007b (0, 1, 1);
+    mcdc007b (1, 0, 1);
+
+    mcdc007c (0, 0, 0);
+    mcdc007c (0, 1, 1);
+    mcdc007c (1, 0, 1);
+
+    mcdc007d (0, 1, 0, 1, 1);
+
+    mcdc008a (0);
+
+    mcdc008b (0);
+
+    mcdc008c (0);
+    mcdc008c (1);
+
+    mcdc008d (0, 0, 0, 0);
+    mcdc008d (1, 0, 0, 0);
+    mcdc008d (1, 0, 1, 0);
+    mcdc008d (1, 0, 1, 1);
+    mcdc008d (1, 1, 1, 1);
+
+    mcdc009a (0, 0);
+    mcdc009a (1, 1);
+
+    mcdc009b (0, 0);
+    mcdc009b (1, 0);
+
+    mcdc010a (0, 0);
+    mcdc010a (0, 9);
+    mcdc010a (2, 1);
+
+    mcdc010b ();
+
+    mcdc010c (0, 0, 0);
+    mcdc010c (0, 1, 0);
+
+    mcdc010d (1);
+
+    mcdc011a (0, 0, 0);
+    mcdc011a (1, 1, 0);
+    mcdc011a (1, 0, 1);
+
+    mcdc012a (0, 0, 0);
+    mcdc012a (0, 1, 1);
+
+    mcdc013a (0, 0, 0);
+    mcdc013a (0, 0, 1);
+    mcdc013a (0, 1, 0);
+    mcdc013a (0, 1, 1);
+    mcdc013a (1, 0, 0);
+    mcdc013a (1, 0, 1);
+    mcdc013a (1, 1, 0);
+    mcdc013a (1, 1, 1);
+
+    mcdc014a ();
+
+    mcdc015a (0, 0);
+    mcdc015a (1, 0);
+
+    mcdc015b (0, 0);
+    mcdc015b (0, 1);
+    mcdc015b (6, 1);
+
+    mcdc015c (0, 0);
+    mcdc015c (0, 5);
+    mcdc015c (6, 1);
+
+    mcdc015d (1, 0, 0);
+
+    mcdc016a (5, 5);
+
+    mcdc016b (5, 5);
+    mcdc016b (6, 5);
+
+    mcdc016c (5, 5);
+
+    mcdc016d (1, 0);
+
+    mcdc017a (0);
+    mcdc017a (2);
+
+    mcdc017b (2, 0);
+    mcdc017b (0, 1);
+
+    mcdc017c (1, 1);
+
+    mcdc018a (0, 0, 1, 1, 0, 0, 0, 0);
+    mcdc018a (0, 1, 0, 0, 0, 0, 1, -2);
+    mcdc018a (0, 6, 0, 0, 0, 0, 1, -2);
+    mcdc018a (0, 6, 0, 0, 0, 0, 1, -2);
+    mcdc018a (0, 0, 0, 1, 0, 1, 1, 0);
+    mcdc018a (1, 0, 0, 0, 1, 1, 0, 0);
+
+    mcdc018b (1, 0, 0);
+    mcdc018b (1, 1, 0);
+
+    mcdc018c (1, 1);
+
+    mcdc019a ();
+
+    mcdc020a (0);
+    mcdc020a (1);
+
+    mcdc020b (0, 0);
+    mcdc020b (1, 0);
+
+    mcdc020c (0, 1);
+    mcdc020c (1, 1);
+
+    mcdc020d (0, 0, 0, 0, 0);
+    mcdc020d (1, 0, 0, 1, 1);
+    mcdc020d (1, 1, 0, 1, 1);
+
+    mcdc021d (1, 0, 1, 0);
+
+    mcdc022a (0, 0);
+
+    mcdc022b (0);
+    mcdc022b (1);
+
+    mcdc022c (0);
+    mcdc022c (1);
+
+    mcdc022d (1);
+    mcdc022e (0, 1, 1, 0);
+
+    mcdc023a (0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1);
+    mcdc023b (0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1);
+    mcdc023c (0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0);
+    mcdc023d (0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1);
+    mcdc023e (0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1);
+    mcdc023f (0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1);
+    mcdc023g (0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1);
+
+    mcdc024a (0, 1);
+    mcdc024b (0, 1);
+    mcdc024c (0, 1);
+    mcdc024d (0, 1);
+    mcdc024a (1, 0);
+    mcdc024b (1, 0);
+    mcdc024c (1, 0);
+    mcdc024d (1, 0);
+
+    mcdc024e (0, 0, 0);
+    mcdc024f (0, 0, 0);
+    mcdc024g (0, 0, 0);
+    mcdc024h (0, 0, 0);
+    mcdc024i (0, 0, 0);
+
+    mcdc025a (0, 0, 1);
+
+    mcdc026a (1, 1, 1, 0, 1);
+    mcdc026a (1, 1, 0, 0, 1);
+    mcdc026a (1, 1, 1, 1, 1);
+
+    mcdc026b (1, 1, 1, 0, 1);
+    mcdc026b (1, 1, 0, 0, 1);
+    mcdc026b (1, 1, 1, 1, 1);
+
+    mcdc026c (1, 1, 1, 0, 1);
+    mcdc026c (1, 1, 0, 0, 1);
+    mcdc026c (1, 1, 1, 1, 1);
+
+    mcdc026d (1, 1, 1, 0, 1);
+    mcdc026d (1, 1, 0, 0, 1);
+    mcdc026d (1, 1, 1, 1, 1);
+
+    mcdc026e (1, 1, 1, 0, 1);
+    mcdc026e (1, 1, 0, 0, 1);
+    mcdc026e (1, 1, 1, 1, 1);
+}
+
+/* { dg-final { run-gcov conditions { --conditions gcov-1.d } } } */
diff --git a/gcc/testsuite/gdc.dg/gcov.exp b/gcc/testsuite/gdc.dg/gcov.exp
new file mode 100644
index 00000000000..4218771b208
--- /dev/null
+++ b/gcc/testsuite/gdc.dg/gcov.exp
@@ -0,0 +1,44 @@
+#   Copyright (C) 1997-2023 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.
+
+# Gcov test driver.
+
+# Load support procs.
+load_lib gdc-dg.exp
+load_lib gcov.exp
+
+global GDC_UNDER_TEST
+
+# For now find gcov in the same directory as $GDC_UNDER_TEST.
+if { ![is_remote host] && [string match "*/*" [lindex $GDC_UNDER_TEST 0]] } {
+    set GCOV [file dirname [lindex $GDC_UNDER_TEST 0]]/[gcc-transform-out-of-tree gcov]
+} else {
+    set GCOV [gcc-transform-out-of-tree gcov]
+}
+
+# Initialize harness.
+dg-init
+
+# Delete old .gcda files.
+set files [glob -nocomplain gcov*.gcda]
+if { $files != "" } {
+    eval "remote_file build delete $files"
+}
+
+# Main loop.
+gdc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/gcov*.d]] "" ""
+
+dg-finish
