Skip to content

Commit ff1c42a

Browse files
committed
[Profiler] Fix throwing expressions in if conditions
Previously we would ignore the effect that an if statement or ternary's condition exit counter might have on its branches, as we assumed a condition can't do any control flow. However, in the case where the condition throws an error, we need to account for the error branch.
1 parent 59275b2 commit ff1c42a

File tree

3 files changed

+450
-15
lines changed

3 files changed

+450
-15
lines changed

lib/SIL/IR/SILProfiler.cpp

+75-15
Original file line numberDiff line numberDiff line change
@@ -1172,6 +1172,20 @@ struct CoverageMapping : public ASTWalker {
11721172
return Action::Continue();
11731173
}
11741174

1175+
class SetParentRAII final {
1176+
ASTWalker &Walker;
1177+
decltype(ASTWalker::Parent) PriorParent;
1178+
1179+
public:
1180+
template <typename T>
1181+
SetParentRAII(ASTWalker &walker, T *newParent)
1182+
: Walker(walker), PriorParent(walker.Parent) {
1183+
walker.Parent = newParent;
1184+
}
1185+
1186+
~SetParentRAII() { Walker.Parent = PriorParent; }
1187+
};
1188+
11751189
PreWalkResult<Stmt *> walkToStmtPre(Stmt *S) override {
11761190
if (S->isImplicit() && S != ImplicitTopLevelBody)
11771191
return Action::Continue(S);
@@ -1186,21 +1200,42 @@ struct CoverageMapping : public ASTWalker {
11861200
pushRegion(SourceMappingRegion::forNode(BS, SM));
11871201

11881202
} else if (auto *IS = dyn_cast<IfStmt>(S)) {
1189-
if (auto *Cond = getConditionNode(IS->getCond()))
1190-
assignCounter(Cond, getCurrentCounter());
1191-
11921203
// The counter for the if statement itself tracks the number of jumps to
11931204
// it by break statements.
11941205
assignCounter(IS, CounterExpr::Zero());
11951206

1196-
// We emit a counter for the then block, and define the else block in
1197-
// terms of it.
1198-
auto ThenCounter = assignKnownCounter(IS->getThenStmt());
1199-
if (IS->getElseStmt()) {
1200-
auto ElseCounter =
1201-
CounterExpr::Sub(getCurrentCounter(), ThenCounter, CounterBuilder);
1202-
assignCounter(IS->getElseStmt(), ElseCounter);
1207+
// FIXME: This is a redundant region.
1208+
if (auto *Cond = getConditionNode(IS->getCond()))
1209+
assignCounter(Cond, getCurrentCounter());
1210+
1211+
// Visit the children.
1212+
// FIXME: This is a hack.
1213+
{
1214+
SetParentRAII R(*this, S);
1215+
for (auto Cond : IS->getCond())
1216+
Cond.walk(*this);
1217+
1218+
// The parent counter is taken after the condition in case e.g
1219+
// it threw an error.
1220+
auto ParentCounter = getCurrentCounter();
1221+
1222+
// We emit a counter for the then block, and define the else block in
1223+
// terms of it.
1224+
auto ThenCounter = assignKnownCounter(IS->getThenStmt());
1225+
IS->getThenStmt()->walk(*this);
1226+
1227+
if (auto *Else = IS->getElseStmt()) {
1228+
auto ElseCounter = CounterExpr::Sub(ParentCounter, ThenCounter,
1229+
CounterBuilder);
1230+
assignCounter(Else, ElseCounter);
1231+
Else->walk(*this);
1232+
}
12031233
}
1234+
// Already visited the children.
1235+
// FIXME: The ASTWalker should do a post-walk for SkipChildren.
1236+
walkToStmtPost(S);
1237+
return Action::SkipChildren(S);
1238+
12041239
} else if (auto *GS = dyn_cast<GuardStmt>(S)) {
12051240
assignCounter(GS, CounterExpr::Zero());
12061241
assignKnownCounter(GS->getBody());
@@ -1235,6 +1270,7 @@ struct CoverageMapping : public ASTWalker {
12351270
// cases.
12361271
assignCounter(SS, CounterExpr::Zero());
12371272

1273+
// FIXME: This is a redundant region.
12381274
assignCounter(SS->getSubjectExpr(), getCurrentCounter());
12391275

12401276
// Assign counters for cases so they're available for fallthrough.
@@ -1393,11 +1429,35 @@ struct CoverageMapping : public ASTWalker {
13931429

13941430
assert(!RegionStack.empty() && "Must be within a region");
13951431

1396-
if (auto *IE = dyn_cast<TernaryExpr>(E)) {
1397-
auto ThenCounter = assignKnownCounter(IE->getThenExpr());
1398-
auto ElseCounter =
1399-
CounterExpr::Sub(getCurrentCounter(), ThenCounter, CounterBuilder);
1400-
assignCounter(IE->getElseExpr(), ElseCounter);
1432+
if (auto *TE = dyn_cast<TernaryExpr>(E)) {
1433+
assert(shouldWalkIntoExpr(TE, Parent, Constant).Action.Action ==
1434+
PreWalkAction::Continue &&
1435+
"Currently this only returns false for closures");
1436+
1437+
// Visit the children.
1438+
// FIXME: This is a hack.
1439+
{
1440+
SetParentRAII R(*this, TE);
1441+
TE->getCondExpr()->walk(*this);
1442+
1443+
// The parent counter is taken after the condition in case e.g
1444+
// it threw an error.
1445+
auto ParentCounter = getCurrentCounter();
1446+
1447+
auto *Then = TE->getThenExpr();
1448+
auto ThenCounter = assignKnownCounter(Then);
1449+
Then->walk(*this);
1450+
1451+
auto *Else = TE->getElseExpr();
1452+
auto ElseCounter =
1453+
CounterExpr::Sub(ParentCounter, ThenCounter, CounterBuilder);
1454+
assignCounter(Else, ElseCounter);
1455+
Else->walk(*this);
1456+
}
1457+
// Already visited the children.
1458+
// FIXME: The ASTWalker should do a post-walk for SkipChildren.
1459+
walkToExprPost(TE);
1460+
return Action::SkipChildren(TE);
14011461
}
14021462
auto WalkResult = shouldWalkIntoExpr(E, Parent, Constant);
14031463
if (WalkResult.Action.Action == PreWalkAction::SkipChildren) {

test/Profiler/coverage_errors.swift

+183
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,11 @@ struct S {
1111
func throwingMethod() throws -> Int { 0 }
1212
}
1313

14+
@discardableResult
1415
func throwingFn() throws -> Int { 0 }
1516

17+
func throwingBool() throws -> Bool { true }
18+
1619
var throwingProp: Int {
1720
get throws { 5 }
1821
}
@@ -632,6 +635,186 @@ func test46() -> (Int, Int)? { // CHECK-NEXT: [[@LINE]]:30 -> [[@LINE+2]]:
632635
try? ({ throw SomeErr.Err1 }(), 0) // CHECK-NEXT: [[@LINE]]:33 -> [[@LINE]]:37 : (0 - 1)
633636
} // CHECK-NEXT: }
634637

638+
// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test47yyKF"
639+
func test47() throws { // CHECK-NEXT: [[@LINE]]:22 -> [[@LINE+2]]:2 : 0
640+
try throwingFn() // CHECK-NEXT: [[@LINE]]:19 -> [[@LINE+1]]:2 : (0 - 1)
641+
} // CHECK-NEXT: }
642+
643+
// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test48SiyKF"
644+
func test48() throws -> Int { // CHECK-NEXT: [[@LINE]]:29 -> [[@LINE+5]]:2 : 0
645+
try throwingBool() // CHECK-NEXT: [[@LINE]]:21 -> [[@LINE+4]]:2 : (0 - 2)
646+
? try throwingFn() // CHECK-NEXT: [[@LINE]]:7 -> [[@LINE]]:23 : 1
647+
: 1 // CHECK-NEXT: [[@LINE-1]]:23 -> [[@LINE+2]]:2 : ((0 - 2) - 3)
648+
// CHECK-NEXT: [[@LINE-1]]:7 -> [[@LINE-1]]:8 : ((0 - 1) - 2)
649+
} // CHECK-NEXT: }
650+
651+
// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test49SiyKF"
652+
func test49() throws -> Int { // CHECK-NEXT: [[@LINE]]:29 -> [[@LINE+6]]:2 : 0
653+
try throwingBool() // CHECK-NEXT: [[@LINE]]:21 -> [[@LINE+5]]:2 : (0 - 2)
654+
? try throwingFn() // CHECK-NEXT: [[@LINE]]:7 -> [[@LINE]]:23 : 1
655+
: try throwingFn() // CHECK-NEXT: [[@LINE-1]]:23 -> [[@LINE+3]]:2 : ((0 - 2) - 3)
656+
// CHECK-NEXT: [[@LINE-1]]:7 -> [[@LINE-1]]:23 : ((0 - 1) - 2)
657+
// CHECK-NEXT: [[@LINE-2]]:23 -> [[@LINE+1]]:2 : (((0 - 2) - 3) - 4)
658+
} // CHECK-NEXT: }
659+
660+
// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test50SiyKF"
661+
func test50() throws -> Int { // CHECK-NEXT: [[@LINE]]:29 -> [[@LINE+8]]:2 : 0
662+
let x = if try throwingBool() { // CHECK-NEXT: [[@LINE]]:14 -> [[@LINE]]:32 : 0
663+
try throwingFn() // CHECK-NEXT: [[@LINE-1]]:32 -> [[@LINE+4]]:11 : (0 - 2)
664+
} else { // CHECK-NEXT: [[@LINE-2]]:33 -> [[@LINE]]:4 : 1
665+
1 // CHECK-NEXT: [[@LINE-2]]:21 -> [[@LINE-1]]:4 : (1 - 3)
666+
} // CHECK-NEXT: [[@LINE-2]]:4 -> [[@LINE+1]]:11 : ((0 - 2) - 3)
667+
return x // CHECK-NEXT: [[@LINE-3]]:10 -> [[@LINE-1]]:4 : ((0 - 1) - 2)
668+
// CHECK-NEXT: [[@LINE-2]]:4 -> [[@LINE-1]]:11 : ((0 - 2) - 3)
669+
} // CHECK-NEXT: }
670+
671+
// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test51SiyKF"
672+
func test51() throws -> Int { // CHECK-NEXT: [[@LINE]]:29 -> [[@LINE+9]]:2 : 0
673+
let x = if try throwingBool() { // CHECK-NEXT: [[@LINE]]:14 -> [[@LINE]]:32 : 0
674+
try throwingFn() // CHECK-NEXT: [[@LINE-1]]:32 -> [[@LINE+4]]:11 : (0 - 2)
675+
} else { // CHECK-NEXT: [[@LINE-2]]:33 -> [[@LINE]]:4 : 1
676+
try throwingFn() // CHECK-NEXT: [[@LINE-2]]:21 -> [[@LINE-1]]:4 : (1 - 3)
677+
} // CHECK-NEXT: [[@LINE-2]]:4 -> [[@LINE+1]]:11 : ((0 - 2) - 3)
678+
return x // CHECK-NEXT: [[@LINE-3]]:10 -> [[@LINE-1]]:4 : ((0 - 1) - 2)
679+
// CHECK-NEXT: [[@LINE-3]]:21 -> [[@LINE-2]]:4 : (((0 - 1) - 2) - 4)
680+
// CHECK-NEXT: [[@LINE-3]]:4 -> [[@LINE-2]]:11 : (((0 - 2) - 3) - 4)
681+
} // CHECK-NEXT: }
682+
683+
// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test52SiyKF"
684+
func test52() throws -> Int { // CHECK-NEXT: [[@LINE]]:29 -> [[@LINE+10]]:2 : 0
685+
let x = if try throwingBool(), // CHECK-NEXT: [[@LINE]]:14 -> [[@LINE]]:32 : 0
686+
try throwingBool() { // CHECK-NEXT: [[@LINE-1]]:32 -> [[@LINE+5]]:11 : (0 - 2)
687+
try throwingFn() // CHECK-NEXT: [[@LINE-1]]:32 -> [[@LINE+4]]:11 : ((0 - 2) - 3)
688+
} else { // CHECK-NEXT: [[@LINE-2]]:33 -> [[@LINE]]:4 : 1
689+
try throwingFn() // CHECK-NEXT: [[@LINE-2]]:21 -> [[@LINE-1]]:4 : (1 - 4)
690+
} // CHECK-NEXT: [[@LINE-2]]:4 -> [[@LINE+1]]:11 : (((0 - 2) - 3) - 4)
691+
return x // CHECK-NEXT: [[@LINE-3]]:10 -> [[@LINE-1]]:4 : (((0 - 1) - 2) - 3)
692+
// CHECK-NEXT: [[@LINE-3]]:21 -> [[@LINE-2]]:4 : ((((0 - 1) - 2) - 3) - 5)
693+
// CHECK-NEXT: [[@LINE-3]]:4 -> [[@LINE-2]]:11 : ((((0 - 2) - 3) - 4) - 5)
694+
} // CHECK-NEXT: }
695+
696+
// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test53yyKF"
697+
func test53() throws { // CHECK-NEXT: [[@LINE]]:22 -> [[@LINE+10]]:2 : 0
698+
if try throwingBool(), // CHECK-NEXT: [[@LINE]]:6 -> [[@LINE]]:24 : 0
699+
try throwingBool() { // CHECK-NEXT: [[@LINE-1]]:24 -> [[@LINE+8]]:2 : (0 - 2)
700+
try throwingFn() // CHECK-NEXT: [[@LINE-1]]:25 -> [[@LINE+7]]:2 : ((0 - 2) - 3)
701+
} else { // CHECK-NEXT: [[@LINE-2]]:26 -> [[@LINE]]:4 : 1
702+
try throwingFn() // CHECK-NEXT: [[@LINE-2]]:21 -> [[@LINE-1]]:4 : (1 - 4)
703+
} // CHECK-NEXT: [[@LINE-2]]:4 -> [[@LINE+4]]:2 : (((0 - 2) - 3) - 4)
704+
// CHECK-NEXT: [[@LINE-3]]:10 -> [[@LINE-1]]:4 : (((0 - 1) - 2) - 3)
705+
// CHECK-NEXT: [[@LINE-3]]:21 -> [[@LINE-2]]:4 : ((((0 - 1) - 2) - 3) - 5)
706+
// CHECK-NEXT: [[@LINE-3]]:4 -> [[@LINE+1]]:2 : ((((0 - 2) - 3) - 4) - 5)
707+
} // CHECK-NEXT: }
708+
709+
// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test54SiSgyF"
710+
func test54()-> Int? { // CHECK-NEXT: [[@LINE]]:22 -> [[@LINE+7]]:2 : 0
711+
if let x = try? throwingFn(),
712+
let y = try? throwingFn() { // CHECK-NEXT: [[@LINE]]:33 -> [[@LINE+2]]:4 : 1
713+
x + y // FIXME: This region is redundant, and not really accurate since we have implicit returns (rdar://118653218)
714+
} else { // CHECK-NEXT: [[@LINE]]:4 -> [[@LINE+3]]:2 : 0
715+
try? throwingFn() // CHECK-NEXT: [[@LINE-1]]:10 -> [[@LINE+1]]:4 : (0 - 1)
716+
} // CHECK-NEXT: [[@LINE]]:4 -> [[@LINE+1]]:2 : 0
717+
} // CHECK-NEXT: }
718+
719+
// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test55yyKF"
720+
func test55() throws { // CHECK-NEXT: [[@LINE]]:22 -> [[@LINE+5]]:2 : 0
721+
while try throwingBool() { // CHECK-NEXT: [[@LINE]]:9 -> [[@LINE]]:27 : (0 + 1)
722+
// CHECK-NEXT: [[@LINE-1]]:27 -> [[@LINE+3]]:2 : (0 - 2)
723+
// CHECK-NEXT: [[@LINE-2]]:28 -> [[@LINE+1]]:4 : 1
724+
} // CHECK-NEXT: [[@LINE]]:4 -> [[@LINE+1]]:2 : (0 - 2)
725+
} // CHECK-NEXT: }
726+
727+
// FIXME: The second condition ought to get a region too (rdar://118649481)
728+
// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test56yyKF"
729+
func test56() throws { // CHECK-NEXT: [[@LINE]]:22 -> [[@LINE+6]]:2 : 0
730+
while try throwingBool(), // CHECK-NEXT: [[@LINE]]:9 -> [[@LINE]]:27 : (0 + 1)
731+
try throwingBool() { // CHECK-NEXT: [[@LINE-1]]:27 -> [[@LINE+4]]:2 : (0 - 2)
732+
// CHECK-NEXT: [[@LINE-1]]:27 -> [[@LINE+3]]:2 : ((0 - 2) - 3)
733+
// CHECK-NEXT: [[@LINE-2]]:28 -> [[@LINE+1]]:4 : 1
734+
} // CHECK-NEXT: [[@LINE]]:4 -> [[@LINE+1]]:2 : ((0 - 2) - 3)
735+
} // CHECK-NEXT: }
736+
737+
// FIXME: We ought to be giving both conditions a region here...
738+
// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test57yyF"
739+
func test57() { // CHECK-NEXT: [[@LINE]]:15 -> [[@LINE+4]]:2 : 0
740+
while let _ = try? throwingFn(),
741+
let _ = try? throwingFn() { // CHECK-NEXT: [[@LINE]]:35 -> [[@LINE+1]]:4 : 1
742+
} // CHECK-NEXT: [[@LINE]]:4 -> [[@LINE+1]]:2 : 0
743+
} // CHECK-NEXT: }
744+
745+
// We generate the same regions for `try!` as `try`. We could handle it
746+
// specially, but the error branches are effectively unreachable, so it
747+
// doesn't make a difference.
748+
// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test58SiyF"
749+
func test58() -> Int { // CHECK-NEXT: [[@LINE]]:22 -> [[@LINE+3]]:2 : 0
750+
let x = try! throwingFn() // CHECK-NEXT: [[@LINE]]:28 -> [[@LINE+1]]:11 : (0 - 1)
751+
return x
752+
} // CHECK-NEXT: }
753+
754+
// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test59SiyKF"
755+
func test59() throws -> Int { // CHECK-NEXT: [[@LINE]]:29 -> [[@LINE+5]]:2 : 0
756+
guard try throwingBool() else { // CHECK-NEXT: [[@LINE]]:27 -> [[@LINE+3]]:11 : (0 - 2)
757+
return 1 // CHECK-NEXT: [[@LINE-1]]:33 -> [[@LINE+1]]:4 : 1
758+
} // CHECK-NEXT: [[@LINE]]:4 -> [[@LINE+1]]:11 : ((0 - 1) - 2)
759+
return 0
760+
} // CHECK-NEXT: }
761+
762+
// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test60SiyKF"
763+
func test60() throws -> Int { // CHECK-NEXT: [[@LINE]]:29 -> [[@LINE+7]]:2 : 0
764+
switch try throwingBool() { // CHECK-NEXT: [[@LINE]]:10 -> [[@LINE]]:28 : 0
765+
case true: // CHECK-NEXT: [[@LINE-1]]:28 -> [[@LINE+5]]:2 : (0 - 1)
766+
return 0 // CHECK-NEXT: [[@LINE-1]]:3 -> [[@LINE]]:13 : 2
767+
case false: // CHECK-NEXT: [[@LINE]]:3 -> [[@LINE+1]]:13 : 3
768+
return 1
769+
}
770+
} // CHECK-NEXT: }
771+
772+
// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test61SiyKF"
773+
func test61() throws -> Int { // CHECK-NEXT: [[@LINE]]:29 -> [[@LINE+7]]:2 : 0
774+
switch try throwingBool() { // CHECK-NEXT: [[@LINE]]:10 -> [[@LINE]]:28 : 0
775+
case true: // CHECK-NEXT: [[@LINE-1]]:28 -> [[@LINE+5]]:2 : (0 - 1)
776+
0 // CHECK-NEXT: [[@LINE-1]]:3 -> [[@LINE]]:6 : 2
777+
case false: // CHECK-NEXT: [[@LINE]]:3 -> [[@LINE+1]]:6 : 3
778+
1 // FIXME: This next region shouldn't be needed, we should know it's unrechabale (rdar://118653218).
779+
} // CHECK-NEXT: [[@LINE]]:4 -> [[@LINE+1]]:2 : (2 + 3)
780+
} // CHECK-NEXT: }
781+
782+
// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test62SiyKF"
783+
func test62() throws -> Int { // CHECK-NEXT: [[@LINE]]:29 -> [[@LINE+8]]:2 : 0
784+
let x = switch try throwingBool() { // CHECK-NEXT: [[@LINE]]:18 -> [[@LINE]]:36 : 0
785+
case true: // CHECK-NEXT: [[@LINE-1]]:36 -> [[@LINE+5]]:11 : (0 - 1)
786+
0 // CHECK-NEXT: [[@LINE-1]]:3 -> [[@LINE]]:6 : 2
787+
case false: // CHECK-NEXT: [[@LINE]]:3 -> [[@LINE+1]]:6 : 3
788+
1
789+
} // CHECK-NEXT: [[@LINE]]:4 -> [[@LINE+1]]:11 : (2 + 3)
790+
return x
791+
} // CHECK-NEXT: }
792+
793+
// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test63yyKF"
794+
func test63() throws { // CHECK-NEXT: [[@LINE]]:22 -> [[@LINE+4]]:2 : 0
795+
for _ in [try throwingFn()] { // CHECK-NEXT: [[@LINE]]:29 -> [[@LINE+3]]:2 : (0 - 2)
796+
// CHECK-NEXT: [[@LINE-1]]:31 -> [[@LINE+1]]:4 : 1
797+
} // CHECK-NEXT: [[@LINE]]:4 -> [[@LINE+1]]:2 : (0 - 2)
798+
} // CHECK-NEXT: }
799+
800+
// FIXME: We don't currently assign a separate region for the where clause, but
801+
// we ought to (rdar://118653191).
802+
// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test64yyKF"
803+
func test64() throws { // CHECK-NEXT: [[@LINE]]:22 -> [[@LINE+5]]:2 : 0
804+
for _ in [0]
805+
where try throwingBool() { // CHECK-NEXT: [[@LINE]]:27 -> [[@LINE+3]]:2 : (0 - 2)
806+
// CHECK-NEXT: [[@LINE-1]]:28 -> [[@LINE+1]]:4 : 1
807+
} // CHECK-NEXT: [[@LINE]]:4 -> [[@LINE+1]]:2 : (0 - 2)
808+
} // CHECK-NEXT: }
809+
810+
// CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test65yyKF"
811+
func test65() throws { // CHECK-NEXT: [[@LINE]]:22 -> [[@LINE+5]]:2 : 0
812+
repeat { // CHECK-NEXT: [[@LINE]]:10 -> [[@LINE+2]]:4 : 1
813+
// CHECK-NEXT: [[@LINE+1]]:4 -> [[@LINE+3]]:2 : 0
814+
} while try throwingBool() // CHECK-NEXT: [[@LINE]]:11 -> [[@LINE]]:29 : 1
815+
// CHECK-NEXT: [[@LINE-1]]:29 -> [[@LINE+1]]:2 : (0 - 2)
816+
} // CHECK-NEXT: }
817+
635818
struct TestInit {
636819
// CHECK-LABEL: sil_coverage_map {{.*}}// coverage_errors.TestInit.init() -> coverage_errors.TestInit
637820
init() { // CHECK-NEXT: [[@LINE]]:10 -> [[@LINE+5]]:4 : 0

0 commit comments

Comments
 (0)