From f4e09c5531302717e393a815a711d14d84e7dac1 Mon Sep 17 00:00:00 2001 From: Hamish Knight Date: Mon, 4 Dec 2023 11:09:01 +0000 Subject: [PATCH 1/2] [AST] Tighten up invariants around IfStmt The 'then' statement must be a BraceStmt, and the 'else' must either be a BraceStmt or an IfStmt. --- include/swift/AST/ASTBridging.h | 3 ++- include/swift/AST/Stmt.h | 19 ++++++++++++------- lib/AST/ASTBridging.cpp | 3 ++- lib/AST/ASTWalker.cpp | 4 ++-- lib/AST/Stmt.cpp | 2 +- lib/ASTGen/Sources/ASTGen/Stmts.swift | 2 +- lib/Sema/BuilderTransform.cpp | 2 +- lib/Sema/CSSyntacticElement.cpp | 2 +- lib/Sema/PCMacro.cpp | 6 +++--- lib/Sema/PlaygroundTransform.cpp | 6 +++--- lib/Sema/TypeCheckStmt.cpp | 14 +++++++------- lib/Sema/TypeCheckStorage.cpp | 11 +++++------ 12 files changed, 40 insertions(+), 34 deletions(-) diff --git a/include/swift/AST/ASTBridging.h b/include/swift/AST/ASTBridging.h index c6f588e0fba86..c5a1799355465 100644 --- a/include/swift/AST/ASTBridging.h +++ b/include/swift/AST/ASTBridging.h @@ -734,7 +734,8 @@ SWIFT_NAME("BridgedIfStmt.createParsed(_:ifKeywordLoc:condition:thenStmt:" "elseLoc:elseStmt:)") BridgedIfStmt BridgedIfStmt_createParsed(BridgedASTContext cContext, BridgedSourceLoc cIfLoc, - BridgedExpr cond, BridgedStmt then, + BridgedExpr cond, + BridgedBraceStmt then, BridgedSourceLoc cElseLoc, BridgedNullableStmt elseStmt); diff --git a/include/swift/AST/Stmt.h b/include/swift/AST/Stmt.h index 324ca414829e6..561e083fcaa16 100644 --- a/include/swift/AST/Stmt.h +++ b/include/swift/AST/Stmt.h @@ -757,20 +757,25 @@ class LabeledConditionalStmt : public LabeledStmt { class IfStmt : public LabeledConditionalStmt { SourceLoc IfLoc; SourceLoc ElseLoc; - Stmt *Then; + BraceStmt *Then; Stmt *Else; public: IfStmt(LabeledStmtInfo LabelInfo, SourceLoc IfLoc, StmtCondition Cond, - Stmt *Then, SourceLoc ElseLoc, Stmt *Else, + BraceStmt *Then, SourceLoc ElseLoc, Stmt *Else, llvm::Optional implicit = llvm::None) : LabeledConditionalStmt(StmtKind::If, getDefaultImplicitFlag(implicit, IfLoc), LabelInfo, Cond), - IfLoc(IfLoc), ElseLoc(ElseLoc), Then(Then), Else(Else) {} + IfLoc(IfLoc), ElseLoc(ElseLoc), Then(Then), Else(Else) { + assert(Then && "Must have non-null 'then' statement"); + assert(!Else || isa(Else) || + isa(Else) && + "Else statement must either be BraceStmt or IfStmt"); + } - IfStmt(SourceLoc IfLoc, Expr *Cond, Stmt *Then, SourceLoc ElseLoc, Stmt *Else, - llvm::Optional implicit, ASTContext &Ctx); + IfStmt(SourceLoc IfLoc, Expr *Cond, BraceStmt *Then, SourceLoc ElseLoc, + Stmt *Else, llvm::Optional implicit, ASTContext &Ctx); SourceLoc getIfLoc() const { return IfLoc; } SourceLoc getElseLoc() const { return ElseLoc; } @@ -782,8 +787,8 @@ class IfStmt : public LabeledConditionalStmt { return (Else ? Else->getEndLoc() : Then->getEndLoc()); } - Stmt *getThenStmt() const { return Then; } - void setThenStmt(Stmt *s) { Then = s; } + BraceStmt *getThenStmt() const { return Then; } + void setThenStmt(BraceStmt *s) { Then = s; } Stmt *getElseStmt() const { return Else; } void setElseStmt(Stmt *s) { Else = s; } diff --git a/lib/AST/ASTBridging.cpp b/lib/AST/ASTBridging.cpp index a0dcc9ae12931..658724387bca7 100644 --- a/lib/AST/ASTBridging.cpp +++ b/lib/AST/ASTBridging.cpp @@ -1051,7 +1051,8 @@ BridgedBraceStmt BridgedBraceStmt_createParsed(BridgedASTContext cContext, BridgedIfStmt BridgedIfStmt_createParsed(BridgedASTContext cContext, BridgedSourceLoc cIfLoc, - BridgedExpr cond, BridgedStmt then, + BridgedExpr cond, + BridgedBraceStmt then, BridgedSourceLoc cElseLoc, BridgedNullableStmt elseStmt) { ASTContext &context = cContext.unbridged(); diff --git a/lib/AST/ASTWalker.cpp b/lib/AST/ASTWalker.cpp index 86e7fa6e8b4df..ef1d00be2b607 100644 --- a/lib/AST/ASTWalker.cpp +++ b/lib/AST/ASTWalker.cpp @@ -1813,8 +1813,8 @@ Stmt *Traversal::visitIfStmt(IfStmt *IS) { if (doIt(IS->getCond())) return nullptr; - if (Stmt *S2 = doIt(IS->getThenStmt())) - IS->setThenStmt(S2); + if (auto *S2 = doIt(IS->getThenStmt())) + IS->setThenStmt(cast(S2)); else return nullptr; diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp index 6f1505f22cb6b..e2a5dac895b7d 100644 --- a/lib/AST/Stmt.cpp +++ b/lib/AST/Stmt.cpp @@ -661,7 +661,7 @@ static StmtCondition exprToCond(Expr *C, ASTContext &Ctx) { return Ctx.AllocateCopy(Arr); } -IfStmt::IfStmt(SourceLoc IfLoc, Expr *Cond, Stmt *Then, SourceLoc ElseLoc, +IfStmt::IfStmt(SourceLoc IfLoc, Expr *Cond, BraceStmt *Then, SourceLoc ElseLoc, Stmt *Else, llvm::Optional implicit, ASTContext &Ctx) : IfStmt(LabeledStmtInfo(), IfLoc, exprToCond(Cond, Ctx), Then, ElseLoc, Else, implicit) {} diff --git a/lib/ASTGen/Sources/ASTGen/Stmts.swift b/lib/ASTGen/Sources/ASTGen/Stmts.swift index 650c025bea3c0..3dafb8c57b9b0 100644 --- a/lib/ASTGen/Sources/ASTGen/Stmts.swift +++ b/lib/ASTGen/Sources/ASTGen/Stmts.swift @@ -73,7 +73,7 @@ extension ASTGenVisitor { self.ctx, ifKeywordLoc: node.ifKeyword.bridgedSourceLoc(in: self), condition: conditions.first!.castToExpr, - thenStmt: self.generate(codeBlock: node.body).asStmt, + thenStmt: self.generate(codeBlock: node.body), elseLoc: node.elseKeyword.bridgedSourceLoc(in: self), elseStmt: node.elseBody.map { switch $0 { diff --git a/lib/Sema/BuilderTransform.cpp b/lib/Sema/BuilderTransform.cpp index 3979747b668e3..5c4c8ac7f7a7c 100644 --- a/lib/Sema/BuilderTransform.cpp +++ b/lib/Sema/BuilderTransform.cpp @@ -494,7 +494,7 @@ class ResultBuilderTransform availabilityCond && builder.supports(ctx.Id_buildLimitedAvailability); NullablePtr thenVarRef; - NullablePtr thenBranch; + NullablePtr thenBranch; { SmallVector thenBody; diff --git a/lib/Sema/CSSyntacticElement.cpp b/lib/Sema/CSSyntacticElement.cpp index b33ae0a39ae6a..4492eab36e0f5 100644 --- a/lib/Sema/CSSyntacticElement.cpp +++ b/lib/Sema/CSSyntacticElement.cpp @@ -1803,7 +1803,7 @@ class SyntacticElementSolutionApplication else hadError = true; - ifStmt->setThenStmt(visit(ifStmt->getThenStmt()).get()); + ifStmt->setThenStmt(castToStmt(visit(ifStmt->getThenStmt()))); if (auto elseStmt = ifStmt->getElseStmt()) { ifStmt->setElseStmt(visit(elseStmt).get()); diff --git a/lib/Sema/PCMacro.cpp b/lib/Sema/PCMacro.cpp index 816167554789a..4fd34e2072c01 100644 --- a/lib/Sema/PCMacro.cpp +++ b/lib/Sema/PCMacro.cpp @@ -142,10 +142,10 @@ class Instrumenter : InstrumenterBase { transformStmtCondition(SC, IS->getStartLoc()); IS->setCond(SC); // FIXME: is setting required?.. - if (Stmt *TS = IS->getThenStmt()) { - Stmt *NTS = transformStmt(TS); + if (auto *TS = IS->getThenStmt()) { + auto *NTS = transformStmt(TS); if (NTS != TS) { - IS->setThenStmt(NTS); + IS->setThenStmt(cast(NTS)); } } diff --git a/lib/Sema/PlaygroundTransform.cpp b/lib/Sema/PlaygroundTransform.cpp index 80e101b8fbc92..9e9869304923b 100644 --- a/lib/Sema/PlaygroundTransform.cpp +++ b/lib/Sema/PlaygroundTransform.cpp @@ -205,10 +205,10 @@ class Instrumenter : InstrumenterBase { // transform*() return their input if it's unmodified, // or a modified copy of their input otherwise. IfStmt *transformIfStmt(IfStmt *IS) { - if (Stmt *TS = IS->getThenStmt()) { - Stmt *NTS = transformStmt(TS); + if (auto *TS = IS->getThenStmt()) { + auto *NTS = transformStmt(TS); if (NTS != TS) { - IS->setThenStmt(NTS); + IS->setThenStmt(cast(NTS)); } } diff --git a/lib/Sema/TypeCheckStmt.cpp b/lib/Sema/TypeCheckStmt.cpp index 44ee8d054f5e2..23f33d465cb5a 100644 --- a/lib/Sema/TypeCheckStmt.cpp +++ b/lib/Sema/TypeCheckStmt.cpp @@ -1377,15 +1377,15 @@ class StmtChecker : public StmtVisitor { auto sourceFile = DC->getParentSourceFile(); checkLabeledStmtShadowing(getASTContext(), sourceFile, IS); - Stmt *S = IS->getThenStmt(); - typeCheckStmt(S); - IS->setThenStmt(S); + auto *TS = IS->getThenStmt(); + typeCheckStmt(TS); + IS->setThenStmt(TS); - if ((S = IS->getElseStmt())) { - typeCheckStmt(S); - IS->setElseStmt(S); + if (auto *ES = IS->getElseStmt()) { + typeCheckStmt(ES); + IS->setElseStmt(ES); } - + return IS; } diff --git a/lib/Sema/TypeCheckStorage.cpp b/lib/Sema/TypeCheckStorage.cpp index ef364293bf3ff..3faf1baad5646 100644 --- a/lib/Sema/TypeCheckStorage.cpp +++ b/lib/Sema/TypeCheckStorage.cpp @@ -1641,14 +1641,13 @@ synthesizeLazyGetterBody(AccessorDecl *Get, VarDecl *VD, VarDecl *Storage, Tmp1DRE->setType(Tmp1VD->getTypeInContext()); auto *Return = new (Ctx) ReturnStmt(SourceLoc(), Tmp1DRE, /*implicit*/true); - + auto *ReturnBranch = BraceStmt::createImplicit(Ctx, {Return}); // Build the "if" around the early return. - Body.push_back(new (Ctx) IfStmt(LabeledStmtInfo(), - SourceLoc(), Ctx.AllocateCopy(Cond), Return, - /*elseloc*/SourceLoc(), /*else*/nullptr, - /*implicit*/ true)); - + Body.push_back(new (Ctx) IfStmt(LabeledStmtInfo(), SourceLoc(), + Ctx.AllocateCopy(Cond), ReturnBranch, + /*elseloc*/ SourceLoc(), + /*else*/ nullptr, /*implicit*/ true)); auto *Tmp2VD = new (Ctx) VarDecl(/*IsStatic*/false, VarDecl::Introducer::Let, SourceLoc(), Ctx.getIdentifier("tmp2"), From c3b055a9a878addfba968967f35a8f7edfb92d36 Mon Sep 17 00:00:00 2001 From: Hamish Knight Date: Mon, 4 Dec 2023 11:09:01 +0000 Subject: [PATCH 2/2] [Profiler] Improve `if` statement coverage Fix counters for regions following `else if`s, fix the counters for `else if` conditions, and fix handling of `break` statements. Also while here, clean up the handling of branch exit regions such that we don't generate multiple overlapping regions for each branch, but a single region at the end of the entire `if` statement that accounts for all exiting control flow. rdar://104078910 rdar://104079242 --- lib/SIL/IR/SILProfiler.cpp | 87 +++++++- test/Profiler/coverage_deinit.swift | 2 +- test/Profiler/coverage_errors.swift | 66 +++--- test/Profiler/coverage_if.swift | 205 +++++++++++++++--- test/Profiler/coverage_if_expr.swift | 20 +- test/Profiler/coverage_optimized_report.swift | 2 +- .../coverage_property_wrapper_backing.swift | 3 +- 7 files changed, 293 insertions(+), 92 deletions(-) diff --git a/lib/SIL/IR/SILProfiler.cpp b/lib/SIL/IR/SILProfiler.cpp index 63d6db422d52f..7aafcec19c495 100644 --- a/lib/SIL/IR/SILProfiler.cpp +++ b/lib/SIL/IR/SILProfiler.cpp @@ -422,6 +422,13 @@ class CounterExpr { /// Returns true if this is a zero counter. bool isZero() const { return Counter.isZero(); } + friend bool operator==(const CounterExpr &LHS, const CounterExpr &RHS) { + return LHS.Counter == RHS.Counter; + } + friend bool operator!=(const CounterExpr &LHS, const CounterExpr &RHS) { + return !(LHS == RHS); + } + llvm::coverage::Counter getLLVMCounter() const { return Counter; } void print(raw_ostream &OS, @@ -476,8 +483,9 @@ class SourceMappingRegion { } SourceMappingRegion(Kind RegionKind, ASTNode Node, SourceRange Range, + llvm::Optional Counter, const SourceManager &SM) - : RegionKind(RegionKind), Node(Node) { + : RegionKind(RegionKind), Node(Node), Counter(Counter) { assert(Range.isValid()); StartLoc = Range.Start; EndLoc = Lexer::getLocForEndOfToken(SM, Range.End); @@ -492,16 +500,18 @@ class SourceMappingRegion { // Note we don't store counters for nodes, as we need to be able to fix them // up later. - return SourceMappingRegion(Kind::Node, Node, Range, SM); + return SourceMappingRegion(Kind::Node, Node, Range, /*Counter*/ llvm::None, + SM); } /// Create a source region for an ASTNode that is only present for scoping of /// child regions, and doesn't need to be included in the resulting set of /// regions. - static SourceMappingRegion scopingOnly(ASTNode Node, - const SourceManager &SM) { + static SourceMappingRegion + scopingOnly(ASTNode Node, const SourceManager &SM, + llvm::Optional Counter = llvm::None) { return SourceMappingRegion(Kind::ScopingOnly, Node, Node.getSourceRange(), - SM); + Counter, SM); } /// Create a refined region for a given counter. @@ -967,6 +977,14 @@ struct CoverageMapping : public ASTWalker { return; } + // Don't apply exit adjustments to if statement branches, they should + // be handled at the end of the statement. This avoids creating awkward + // overlapping exit regions for each branch, and ensures 'break' + // statements only have their jump counted once for the entire + // statement. + if (isa(ParentStmt)) + return; + if (auto *LS = dyn_cast(ParentStmt)) JumpsToLabel = getCounter(LS); } @@ -1225,7 +1243,7 @@ struct CoverageMapping : public ASTWalker { // it by break statements. assignCounter(IS, CounterExpr::Zero()); - // FIXME: This is a redundant region. + // FIXME: This is a redundant region for non else-ifs. if (auto *Cond = getConditionNode(IS->getCond())) assignCounter(Cond, getCurrentCounter()); @@ -1244,13 +1262,68 @@ struct CoverageMapping : public ASTWalker { // terms of it. auto ThenCounter = assignKnownCounter(IS->getThenStmt()); IS->getThenStmt()->walk(*this); + auto ThenDelta = + CounterExpr::Sub(ThenCounter, getExitCounter(), CounterBuilder); + llvm::Optional ElseDelta; if (auto *Else = IS->getElseStmt()) { auto ElseCounter = CounterExpr::Sub(ParentCounter, ThenCounter, CounterBuilder); - assignCounter(Else, ElseCounter); + // We handle `else if` and `else` slightly differently here. For + // `else` we have a BraceStmt, and can use the existing scoping logic + // to handle calculating the exit count. For `else if`, we need to + // set up a new scope to contain the child `if` statement, effectively + // we treat: + // + // if .random() { + // } else if .random() { + // } else { + // } + // + // the same as: + // + // if .random() { + // } else { + // if .random() { + // } else { + // } + // } + // + // This ensures we assign a correct counter to the `else if` + // condition, and allows us to compute the exit count correctly. We + // don't need the fake `else` scope to be included in the resulting + // set of regions, so we mark it scoping-only. + if (isa(Else)) { + assignCounter(Else, ElseCounter); + } else { + pushRegion(SourceMappingRegion::scopingOnly(Else, SM, ElseCounter)); + } Else->walk(*this); + + // Once we've walked the `else`, compute the delta exit count. For + // a normal `else` we can use the computed exit count, for an + // `else if` we can take the current region count since we don't have + // a proper scope. This is a little hacked together, but we'll be able + // to do away with all of this once we re-implement as a SILOptimizer + // pass. + auto AfterElse = isa(Else) ? getExitCounter() + : getCurrentCounter(); + if (!isa(Else)) + popRegions(Else); + + ElseDelta = CounterExpr::Sub(ElseCounter, AfterElse, CounterBuilder); } + // Compute the exit count following the `if`, taking jumps to the + // statement by breaks into account, and the delta of the `then` branch + // and `else` branch if we have one. + auto AfterIf = getCurrentCounter(); + AfterIf = CounterExpr::Add(AfterIf, getCounter(IS), CounterBuilder); + AfterIf = CounterExpr::Sub(AfterIf, ThenDelta, CounterBuilder); + if (ElseDelta) + AfterIf = CounterExpr::Sub(AfterIf, *ElseDelta, CounterBuilder); + + if (AfterIf != getCurrentCounter()) + replaceCount(AfterIf, getEndLoc(IS)); } // Already visited the children. // FIXME: The ASTWalker should do a post-walk for SkipChildren. diff --git a/test/Profiler/coverage_deinit.swift b/test/Profiler/coverage_deinit.swift index 27d8cb4ac9ccf..4acebb01b329b 100644 --- a/test/Profiler/coverage_deinit.swift +++ b/test/Profiler/coverage_deinit.swift @@ -21,4 +21,4 @@ public class Foo { // CHECK-NEXT: [[@LINE-8]]:10 -> [[@LINE-4]]:4 : 0 // CHECK-NEXT: [[@LINE-8]]:8 -> [[@LINE-8]]:17 : 0 // CHECK-NEXT: [[@LINE-9]]:18 -> [[@LINE-7]]:6 : 1 -// CHECK-NEXT: [[@LINE-8]]:6 -> [[@LINE-7]]:4 : 0 +// CHECK-NEXT: } diff --git a/test/Profiler/coverage_errors.swift b/test/Profiler/coverage_errors.swift index a7d829cfb17fd..b0dbe109884c3 100644 --- a/test/Profiler/coverage_errors.swift +++ b/test/Profiler/coverage_errors.swift @@ -658,62 +658,58 @@ func test49() throws -> Int { // CHECK-NEXT: [[@LINE]]:29 -> [[@LINE+6]]:2 : } // CHECK-NEXT: } // CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test50SiyKF" -func test50() throws -> Int { // CHECK-NEXT: [[@LINE]]:29 -> [[@LINE+8]]:2 : 0 +func test50() throws -> Int { // CHECK-NEXT: [[@LINE]]:29 -> [[@LINE+7]]:2 : 0 let x = if try throwingBool() { // CHECK-NEXT: [[@LINE]]:14 -> [[@LINE]]:32 : 0 try throwingFn() // CHECK-NEXT: [[@LINE-1]]:32 -> [[@LINE+4]]:11 : (0 - 2) } else { // CHECK-NEXT: [[@LINE-2]]:33 -> [[@LINE]]:4 : 1 1 // CHECK-NEXT: [[@LINE-2]]:21 -> [[@LINE-1]]:4 : (1 - 3) - } // CHECK-NEXT: [[@LINE-2]]:4 -> [[@LINE+1]]:11 : ((0 - 2) - 3) - return x // CHECK-NEXT: [[@LINE-3]]:10 -> [[@LINE-1]]:4 : ((0 - 1) - 2) - // CHECK-NEXT: [[@LINE-2]]:4 -> [[@LINE-1]]:11 : ((0 - 2) - 3) + } // CHECK-NEXT: [[@LINE-2]]:10 -> [[@LINE]]:4 : ((0 - 1) - 2) + return x // CHECK-NEXT: [[@LINE-1]]:4 -> [[@LINE]]:11 : ((0 - 2) - 3) } // CHECK-NEXT: } // CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test51SiyKF" -func test51() throws -> Int { // CHECK-NEXT: [[@LINE]]:29 -> [[@LINE+9]]:2 : 0 +func test51() throws -> Int { // CHECK-NEXT: [[@LINE]]:29 -> [[@LINE+8]]:2 : 0 let x = if try throwingBool() { // CHECK-NEXT: [[@LINE]]:14 -> [[@LINE]]:32 : 0 try throwingFn() // CHECK-NEXT: [[@LINE-1]]:32 -> [[@LINE+4]]:11 : (0 - 2) } else { // CHECK-NEXT: [[@LINE-2]]:33 -> [[@LINE]]:4 : 1 try throwingFn() // CHECK-NEXT: [[@LINE-2]]:21 -> [[@LINE-1]]:4 : (1 - 3) - } // CHECK-NEXT: [[@LINE-2]]:4 -> [[@LINE+1]]:11 : ((0 - 2) - 3) - return x // CHECK-NEXT: [[@LINE-3]]:10 -> [[@LINE-1]]:4 : ((0 - 1) - 2) - // CHECK-NEXT: [[@LINE-3]]:21 -> [[@LINE-2]]:4 : (((0 - 1) - 2) - 4) - // CHECK-NEXT: [[@LINE-3]]:4 -> [[@LINE-2]]:11 : (((0 - 2) - 3) - 4) + } // CHECK-NEXT: [[@LINE-2]]:10 -> [[@LINE]]:4 : ((0 - 1) - 2) + return x // CHECK-NEXT: [[@LINE-2]]:21 -> [[@LINE-1]]:4 : (((0 - 1) - 2) - 4) + // CHECK-NEXT: [[@LINE-2]]:4 -> [[@LINE-1]]:11 : (((0 - 2) - 3) - 4) } // CHECK-NEXT: } // CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test52SiyKF" -func test52() throws -> Int { // CHECK-NEXT: [[@LINE]]:29 -> [[@LINE+10]]:2 : 0 - let x = if try throwingBool(), // CHECK-NEXT: [[@LINE]]:14 -> [[@LINE]]:32 : 0 - try throwingBool() { // CHECK-NEXT: [[@LINE-1]]:32 -> [[@LINE+5]]:11 : (0 - 2) - try throwingFn() // CHECK-NEXT: [[@LINE-1]]:32 -> [[@LINE+4]]:11 : ((0 - 2) - 3) - } else { // CHECK-NEXT: [[@LINE-2]]:33 -> [[@LINE]]:4 : 1 - try throwingFn() // CHECK-NEXT: [[@LINE-2]]:21 -> [[@LINE-1]]:4 : (1 - 4) - } // CHECK-NEXT: [[@LINE-2]]:4 -> [[@LINE+1]]:11 : (((0 - 2) - 3) - 4) - return x // CHECK-NEXT: [[@LINE-3]]:10 -> [[@LINE-1]]:4 : (((0 - 1) - 2) - 3) - // CHECK-NEXT: [[@LINE-3]]:21 -> [[@LINE-2]]:4 : ((((0 - 1) - 2) - 3) - 5) - // CHECK-NEXT: [[@LINE-3]]:4 -> [[@LINE-2]]:11 : ((((0 - 2) - 3) - 4) - 5) +func test52() throws -> Int { // CHECK-NEXT: [[@LINE]]:29 -> [[@LINE+9]]:2 : 0 + let x = if try throwingBool(), // CHECK-NEXT: [[@LINE]]:14 -> [[@LINE]]:32 : 0 + try throwingBool() { // CHECK-NEXT: [[@LINE-1]]:32 -> [[@LINE+5]]:11 : (0 - 2) + try throwingFn() // CHECK-NEXT: [[@LINE-1]]:32 -> [[@LINE+4]]:11 : ((0 - 2) - 3) + } else { // CHECK-NEXT: [[@LINE-2]]:33 -> [[@LINE]]:4 : 1 + try throwingFn() // CHECK-NEXT: [[@LINE-2]]:21 -> [[@LINE-1]]:4 : (1 - 4) + } // CHECK-NEXT: [[@LINE-2]]:10 -> [[@LINE]]:4 : (((0 - 1) - 2) - 3) + return x // CHECK-NEXT: [[@LINE-2]]:21 -> [[@LINE-1]]:4 : ((((0 - 1) - 2) - 3) - 5) + // CHECK-NEXT: [[@LINE-2]]:4 -> [[@LINE-1]]:11 : ((((0 - 2) - 3) - 4) - 5) } // CHECK-NEXT: } // CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test53yyKF" -func test53() throws { // CHECK-NEXT: [[@LINE]]:22 -> [[@LINE+10]]:2 : 0 - if try throwingBool(), // CHECK-NEXT: [[@LINE]]:6 -> [[@LINE]]:24 : 0 - try throwingBool() { // CHECK-NEXT: [[@LINE-1]]:24 -> [[@LINE+8]]:2 : (0 - 2) - try throwingFn() // CHECK-NEXT: [[@LINE-1]]:25 -> [[@LINE+7]]:2 : ((0 - 2) - 3) - } else { // CHECK-NEXT: [[@LINE-2]]:26 -> [[@LINE]]:4 : 1 - try throwingFn() // CHECK-NEXT: [[@LINE-2]]:21 -> [[@LINE-1]]:4 : (1 - 4) - } // CHECK-NEXT: [[@LINE-2]]:4 -> [[@LINE+4]]:2 : (((0 - 2) - 3) - 4) - // CHECK-NEXT: [[@LINE-3]]:10 -> [[@LINE-1]]:4 : (((0 - 1) - 2) - 3) - // CHECK-NEXT: [[@LINE-3]]:21 -> [[@LINE-2]]:4 : ((((0 - 1) - 2) - 3) - 5) - // CHECK-NEXT: [[@LINE-3]]:4 -> [[@LINE+1]]:2 : ((((0 - 2) - 3) - 4) - 5) +func test53() throws { // CHECK-NEXT: [[@LINE]]:22 -> [[@LINE+9]]:2 : 0 + if try throwingBool(), // CHECK-NEXT: [[@LINE]]:6 -> [[@LINE]]:24 : 0 + try throwingBool() { // CHECK-NEXT: [[@LINE-1]]:24 -> [[@LINE+7]]:2 : (0 - 2) + try throwingFn() // CHECK-NEXT: [[@LINE-1]]:25 -> [[@LINE+6]]:2 : ((0 - 2) - 3) + } else { // CHECK-NEXT: [[@LINE-2]]:26 -> [[@LINE]]:4 : 1 + try throwingFn() // CHECK-NEXT: [[@LINE-2]]:21 -> [[@LINE-1]]:4 : (1 - 4) + } // CHECK-NEXT: [[@LINE-2]]:10 -> [[@LINE]]:4 : (((0 - 1) - 2) - 3) + // CHECK-NEXT: [[@LINE-2]]:21 -> [[@LINE-1]]:4 : ((((0 - 1) - 2) - 3) - 5) + // CHECK-NEXT: [[@LINE-2]]:4 -> [[@LINE+1]]:2 : ((((0 - 2) - 3) - 4) - 5) } // CHECK-NEXT: } // CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test54SiSgyF" -func test54()-> Int? { // CHECK-NEXT: [[@LINE]]:22 -> [[@LINE+7]]:2 : 0 +func test54()-> Int? { // CHECK-NEXT: [[@LINE]]:22 -> [[@LINE+7]]:2 : 0 if let x = try? throwingFn(), - let y = try? throwingFn() { // CHECK-NEXT: [[@LINE]]:33 -> [[@LINE+2]]:4 : 1 - x + y // FIXME: This region is redundant, and not really accurate since we have implicit returns (rdar://118653218) - } else { // CHECK-NEXT: [[@LINE]]:4 -> [[@LINE+3]]:2 : 0 - try? throwingFn() // CHECK-NEXT: [[@LINE-1]]:10 -> [[@LINE+1]]:4 : (0 - 1) - } // CHECK-NEXT: [[@LINE]]:4 -> [[@LINE+1]]:2 : 0 + let y = try? throwingFn() { // CHECK-NEXT: [[@LINE]]:33 -> [[@LINE+2]]:4 : 1 + x + y + } else { // CHECK-NEXT: [[@LINE]]:10 -> [[@LINE+2]]:4 : (0 - 1) + try? throwingFn() + } } // CHECK-NEXT: } // CHECK-LABEL: sil_coverage_map {{.*}} "$s15coverage_errors6test55yyKF" diff --git a/test/Profiler/coverage_if.swift b/test/Profiler/coverage_if.swift index 9b3a3b0361d4f..30dce6880e8dd 100644 --- a/test/Profiler/coverage_if.swift +++ b/test/Profiler/coverage_if.swift @@ -21,15 +21,14 @@ foo(x: false); // rdar://29390569 – Make sure we don't add a spurious unreachable empty region. // CHECK-LABEL: sil_coverage_map {{.*}}// coverage_if.foo1 -func foo1() -> Int { // CHECK: [[@LINE]]:20 -> {{[0-9]+}}:2 : 0 - if .random() { // CHECK: [[@LINE]]:6 -> [[@LINE]]:15 : 0 - return 0 // CHECK: [[@LINE-1]]:16 -> [[@LINE+2]]:4 : 1 - // CHECK: [[@LINE+1]]:4 -> {{[0-9]+}}:2 : (0 - 1) - } else if .random() { // CHECK: [[@LINE]]:13 -> [[@LINE]]:22 : (0 - 1) - return 1 // CHECK: [[@LINE-1]]:23 -> [[@LINE+1]]:4 : 2 - } else { // CHECK: [[@LINE]]:4 -> {{[0-9]+}}:2 : ((0 - 1) - 2) - return 2 // CHECK: [[@LINE-1]]:10 -> [[@LINE+1]]:4 : ((0 - 1) - 2) - } // CHECK-NOT: zero +func foo1() -> Int { // CHECK-NEXT: [[@LINE]]:20 -> {{[0-9]+}}:2 : 0 + if .random() { // CHECK-NEXT: [[@LINE]]:6 -> [[@LINE]]:15 : 0 + return 0 // CHECK-NEXT: [[@LINE-1]]:16 -> [[@LINE+1]]:4 : 1 + } else if .random() { // CHECK-NEXT: [[@LINE]]:13 -> [[@LINE]]:22 : (0 - 1) + return 1 // CHECK-NEXT: [[@LINE-1]]:23 -> [[@LINE+1]]:4 : 2 + } else { // CHECK-NEXT: [[@LINE]]:10 -> [[@LINE+2]]:4 : ((0 - 1) - 2) + return 2 + } // CHECK-NEXT: } } // ...but we will add an unreachable region if you write code there. @@ -47,16 +46,17 @@ func foo2() -> Int { // Make sure we don't add unreachable regions for a labeled jump either. // CHECK-LABEL: sil_coverage_map {{.*}}// coverage_if.foo3 -func foo3() -> Int { // CHECK: [[@LINE]]:20 -> {{[0-9]+}}:2 : 0 - x: do { // CHECK: [[@LINE]]:9 -> [[@LINE+6]]:4 : 0 - if .random() { // CHECK: [[@LINE]]:8 -> [[@LINE]]:17 : 0 - return 0 // CHECK: [[@LINE-1]]:18 -> [[@LINE+1]]:6 : 1 - } else { // CHECK: [[@LINE]]:6 -> [[@LINE+3]]:4 : (0 - 1) - break x // CHECK: [[@LINE-1]]:12 -> [[@LINE+1]]:6 : (0 - 1) - } // CHECK-NOT: zero - } +func foo3() -> Int { // CHECK-NEXT: [[@LINE]]:20 -> {{[0-9]+}}:2 : 0 + x: do { // CHECK-NEXT: [[@LINE]]:9 -> [[@LINE+6]]:4 : 0 + if .random() { // CHECK-NEXT: [[@LINE]]:8 -> [[@LINE]]:17 : 0 + return 0 // CHECK-NEXT: [[@LINE-1]]:18 -> [[@LINE+1]]:6 : 1 + } else { // CHECK-NEXT: [[@LINE]]:12 -> [[@LINE+2]]:6 : (0 - 1) + break x + } + } // CHECK-NEXT: [[@LINE]]:4 -> [[@LINE+1]]:11 : (0 - 1) return 2 -} +} // CHECK-NEXT: } + // CHECK-LABEL: sil_coverage_map {{.*}}// coverage_if.foo4 func foo4() -> Int { x: do { @@ -71,20 +71,161 @@ func foo4() -> Int { } // CHECK-LABEL: sil_coverage_map {{.*}}// coverage_if.foo5 -func foo5() throws -> Int { // CHECK: [[@LINE]]:27 -> {{[0-9]+}}:2 : 0 - if .random() { // CHECK: [[@LINE]]:6 -> [[@LINE]]:15 : 0 - return 0 // CHECK: [[@LINE-1]]:16 -> [[@LINE+1]]:4 : 1 - } else { // CHECK: [[@LINE]]:4 -> {{[0-9]+}}:2 : (0 - 1) - struct S: Error {} // CHECK: [[@LINE-1]]:10 -> [[@LINE+2]]:4 : (0 - 1) +func foo5() throws -> Int { // CHECK-NEXT: [[@LINE]]:27 -> {{[0-9]+}}:2 : 0 + if .random() { // CHECK-NEXT: [[@LINE]]:6 -> [[@LINE]]:15 : 0 + return 0 // CHECK-NEXT: [[@LINE-1]]:16 -> [[@LINE+1]]:4 : 1 + } else { // CHECK-NEXT: [[@LINE]]:10 -> [[@LINE+3]]:4 : (0 - 1) + struct S: Error {} throw S() - } // CHECK-NOT: zero -} + } +} // CHECK-NEXT: } // CHECK-LABEL: sil_coverage_map {{.*}}// coverage_if.foo6 -func foo6(_ x: Int?) -> Int? { // CHECK: [[@LINE]]:30 -> {{[0-9]+}}:2 : 0 - if let x = x { - return x // CHECK: [[@LINE-1]]:16 -> [[@LINE+1]]:4 : 1 - } else { // CHECK: [[@LINE]]:4 -> {{[0-9]+}}:2 : (0 - 1) - return nil // CHECK: [[@LINE-1]]:10 -> [[@LINE+1]]:4 : (0 - 1) - } // CHECK-NOT: zero -} +func foo6(_ x: Int?) -> Int? { // CHECK-NEXT: [[@LINE]]:30 -> {{[0-9]+}}:2 : 0 + if let x = x { // CHECK-NEXT: [[@LINE]]:16 -> [[@LINE+2]]:4 : 1 + return x + } else { // CHECK-NEXT: [[@LINE]]:10 -> [[@LINE+2]]:4 : (0 - 1) + return nil + } +} // CHECK-NEXT: } + +// rdar://104078910, rdar://104079242 - Make sure the else if condition and the +// else gets a correct counter here. +// CHECK-LABEL: sil_coverage_map {{.*}}// coverage_if.foo7 +func foo7() -> Int { // CHECK-NEXT: [[@LINE]]:20 -> [[@LINE+12]]:2 : 0 + let x: Int + if .random() { // CHECK-NEXT: [[@LINE]]:6 -> [[@LINE]]:15 : 0 + x = 0 // CHECK-NEXT: [[@LINE-1]]:16 -> [[@LINE+1]]:4 : 1 + } else if .random() { // CHECK-NEXT: [[@LINE]]:13 -> [[@LINE]]:22 : (0 - 1) + x = 1 // CHECK-NEXT: [[@LINE-1]]:23 -> [[@LINE+1]]:4 : 2 + } else if .random() { // CHECK-NEXT: [[@LINE]]:13 -> [[@LINE]]:22 : ((0 - 1) - 2) + x = 2 // CHECK-NEXT: [[@LINE-1]]:23 -> [[@LINE+1]]:4 : 3 + } else { // CHECK-NEXT: [[@LINE]]:10 -> [[@LINE+2]]:4 : (((0 - 1) - 2) - 3) + x = 3 + } + return x +} // CHECK-NEXT: } + +// CHECK-LABEL: sil_coverage_map {{.*}}// coverage_if.foo8 +func foo8() -> Int { // CHECK-NEXT: [[@LINE]]:20 -> [[@LINE+12]]:2 : 0 + let x: Int // CHECK-NEXT: [[@LINE+1]]:6 -> [[@LINE+1]]:15 : 0 + if .random() { // CHECK-NEXT: [[@LINE]]:16 -> [[@LINE+2]]:4 : 1 + return 0 + } else if .random() { // CHECK-NEXT: [[@LINE]]:13 -> [[@LINE]]:22 : (0 - 1) + x = 1 // CHECK-NEXT: [[@LINE-1]]:23 -> [[@LINE+1]]:4 : 2 + } else if .random() { // CHECK-NEXT: [[@LINE]]:13 -> [[@LINE]]:22 : ((0 - 1) - 2) + x = 2 // CHECK-NEXT: [[@LINE-1]]:23 -> [[@LINE+1]]:4 : 3 + } else { // CHECK-NEXT: [[@LINE]]:10 -> [[@LINE+2]]:4 : (((0 - 1) - 2) - 3) + x = 3 + } // CHECK-NEXT: [[@LINE]]:4 -> [[@LINE+1]]:11 : (0 - 1) + return x +} // CHECK-NEXT: } + +// CHECK-LABEL: sil_coverage_map {{.*}}// coverage_if.foo9 +func foo9() -> Int { // CHECK-NEXT: [[@LINE]]:20 -> [[@LINE+12]]:2 : 0 + let x: Int // CHECK-NEXT: [[@LINE+1]]:6 -> [[@LINE+1]]:15 : 0 + if .random() { // CHECK-NEXT: [[@LINE]]:16 -> [[@LINE+2]]:4 : 1 + return 0 + } else if .random() { // CHECK-NEXT: [[@LINE]]:13 -> [[@LINE]]:22 : (0 - 1) + return 1 // CHECK-NEXT: [[@LINE-1]]:23 -> [[@LINE+1]]:4 : 2 + } else if .random() { // CHECK-NEXT: [[@LINE]]:13 -> [[@LINE]]:22 : ((0 - 1) - 2) + x = 2 // CHECK-NEXT: [[@LINE-1]]:23 -> [[@LINE+1]]:4 : 3 + } else { // CHECK-NEXT: [[@LINE]]:10 -> [[@LINE+2]]:4 : (((0 - 1) - 2) - 3) + x = 3 + } // CHECK-NEXT: [[@LINE]]:4 -> [[@LINE+1]]:11 : ((0 - 1) - 2) + return x +} // CHECK-NEXT: } + +// CHECK-LABEL: sil_coverage_map {{.*}}// coverage_if.foo10 +func foo10() -> Int { // CHECK-NEXT: [[@LINE]]:21 -> [[@LINE+12]]:2 : 0 + let x: Int // CHECK-NEXT: [[@LINE+1]]:6 -> [[@LINE+1]]:15 : 0 + if .random() { // CHECK-NEXT: [[@LINE]]:16 -> [[@LINE+2]]:4 : 1 + return 0 + } else if .random() { // CHECK-NEXT: [[@LINE]]:13 -> [[@LINE]]:22 : (0 - 1) + return 1 // CHECK-NEXT: [[@LINE-1]]:23 -> [[@LINE+1]]:4 : 2 + } else if .random() { // CHECK-NEXT: [[@LINE]]:13 -> [[@LINE]]:22 : ((0 - 1) - 2) + x = 2 // CHECK-NEXT: [[@LINE-1]]:23 -> [[@LINE+1]]:4 : 3 + } else { // CHECK-NEXT: [[@LINE]]:10 -> [[@LINE+2]]:4 : (((0 - 1) - 2) - 3) + return 3 + } // CHECK-NEXT: [[@LINE]]:4 -> [[@LINE+1]]:11 : 3 + return x +} // CHECK-NEXT: } + +// CHECK-LABEL: sil_coverage_map {{.*}}// coverage_if.foo11 +func foo11() -> Int { // CHECK-NEXT: [[@LINE]]:21 -> [[@LINE+12]]:2 : 0 + let x: Int // CHECK-NEXT: [[@LINE+1]]:6 -> [[@LINE+1]]:15 : 0 + if .random() { // CHECK-NEXT: [[@LINE]]:16 -> [[@LINE+2]]:4 : 1 + x = 0 + } else if .random() { // CHECK-NEXT: [[@LINE]]:13 -> [[@LINE]]:22 : (0 - 1) + x = 1 // CHECK-NEXT: [[@LINE-1]]:23 -> [[@LINE+1]]:4 : 2 + } else if .random() { // CHECK-NEXT: [[@LINE]]:13 -> [[@LINE]]:22 : ((0 - 1) - 2) + x = 2 // CHECK-NEXT: [[@LINE-1]]:23 -> [[@LINE+1]]:4 : 3 + } else { // CHECK-NEXT: [[@LINE]]:10 -> [[@LINE+2]]:4 : (((0 - 1) - 2) - 3) + return 3 + } // CHECK-NEXT: [[@LINE]]:4 -> [[@LINE+1]]:11 : ((1 + 2) + 3) + return x +} // CHECK-NEXT: } + +// CHECK-LABEL: sil_coverage_map {{.*}}// coverage_if.foo12 +func foo12() -> Int { // CHECK-NEXT: [[@LINE]]:21 -> [[@LINE+9]]:2 : 0 + let x: Int + y: if .random() { // CHECK-NEXT: [[@LINE]]:9 -> [[@LINE]]:18 : 0 + x = 0 // CHECK-NEXT: [[@LINE-1]]:19 -> [[@LINE+2]]:4 : 1 + break y + } else { + x = 1 // CHECK-NEXT: [[@LINE-1]]:10 -> [[@LINE+1]]:4 : (0 - 1) + } + return x +} // CHECK-NEXT: } + +// CHECK-LABEL: sil_coverage_map {{.*}}// coverage_if.foo13 +func foo13() -> Int { // CHECK-NEXT: [[@LINE]]:21 -> [[@LINE+10]]:2 : 0 + let x: Int + y: if .random() { // CHECK-NEXT: [[@LINE]]:9 -> [[@LINE]]:18 : 0 + x = 0 // CHECK-NEXT: [[@LINE-1]]:19 -> [[@LINE+2]]:4 : 1 + break y + } else { + x = 1 // CHECK-NEXT: [[@LINE-1]]:10 -> [[@LINE+2]]:4 : (0 - 1) + break y + } + return x +} // CHECK-NEXT: } + +// CHECK-LABEL: sil_coverage_map {{.*}}// coverage_if.foo14 +func foo14() -> Int { // CHECK-NEXT: [[@LINE]]:21 -> [[@LINE+14]]:2 : 0 + let x: Int // CHECK-NEXT: [[@LINE+1]]:9 -> [[@LINE+1]]:18 : 0 + y: if .random() { // CHECK-NEXT: [[@LINE]]:19 -> [[@LINE+3]]:4 : 1 + x = 0 + break y + } else if .random() { // CHECK-NEXT: [[@LINE]]:13 -> [[@LINE]]:22 : (0 - 1) + return 1 // CHECK-NEXT: [[@LINE-1]]:23 -> [[@LINE+1]]:4 : 2 + } else if .random() { // CHECK-NEXT: [[@LINE]]:13 -> [[@LINE]]:22 : ((0 - 1) - 2) + x = 2 // CHECK-NEXT: [[@LINE-1]]:23 -> [[@LINE+2]]:4 : 3 + break y + } else { // CHECK-NEXT: [[@LINE]]:10 -> [[@LINE+2]]:4 : (((0 - 1) - 2) - 3) + return 3 + } // CHECK-NEXT: [[@LINE]]:4 -> [[@LINE+1]]:11 : (1 + 3) + return x +} // CHECK-NEXT: } + +// CHECK-LABEL: sil_coverage_map {{.*}}// coverage_if.foo15 +func foo15() -> Int { // CHECK-NEXT: [[@LINE]]:21 -> [[@LINE+19]]:2 : 0 + let x: Int // CHECK-NEXT: [[@LINE+1]]:9 -> [[@LINE+1]]:18 : 0 + y: if .random() { // CHECK-NEXT: [[@LINE]]:19 -> [[@LINE+5]]:4 : 1 + x = 0 + if .random() { // CHECK-NEXT: [[@LINE]]:8 -> [[@LINE]]:17 : 1 + break y // CHECK-NEXT: [[@LINE-1]]:18 -> [[@LINE+1]]:6 : 2 + } // CHECK-NEXT: [[@LINE]]:6 -> [[@LINE+1]]:4 : (1 - 2) + } else if .random() { // CHECK-NEXT: [[@LINE]]:13 -> [[@LINE]]:22 : (0 - 1) + x = 1 // CHECK-NEXT: [[@LINE-1]]:23 -> [[@LINE+4]]:4 : 3 + if .random() { // CHECK-NEXT: [[@LINE]]:8 -> [[@LINE]]:17 : 3 + return 1 // CHECK-NEXT: [[@LINE-1]]:18 -> [[@LINE+1]]:6 : 4 + } // CHECK-NEXT: [[@LINE]]:6 -> [[@LINE+1]]:4 : (3 - 4) + } else if .random() { // CHECK-NEXT: [[@LINE]]:13 -> [[@LINE]]:22 : ((0 - 1) - 3) + x = 2 // CHECK-NEXT: [[@LINE-1]]:23 -> [[@LINE+2]]:4 : 5 + break y + } else { // CHECK-NEXT: [[@LINE]]:10 -> [[@LINE+2]]:4 : (((0 - 1) - 3) - 5) + return 3 + } // CHECK-NEXT: [[@LINE]]:4 -> [[@LINE+1]]:11 : (((1 + 3) + 5) - 4) + return x +} // CHECK-NEXT: } diff --git a/test/Profiler/coverage_if_expr.swift b/test/Profiler/coverage_if_expr.swift index 81dfe258b98bf..2f27c2ce96696 100644 --- a/test/Profiler/coverage_if_expr.swift +++ b/test/Profiler/coverage_if_expr.swift @@ -2,20 +2,12 @@ // RUN: %target-swift-frontend -profile-generate -profile-coverage-mapping -emit-ir %s // CHECK-LABEL: sil_coverage_map {{.*}} "$s16coverage_if_expr0b1_C0SiyF" -func if_expr() -> Int { // CHECK: [[@LINE]]:23 -> {{[0-9]+}}:2 : 0 - if .random() { // CHECK-NEXT: [[@LINE]]:6 -> [[@LINE]]:15 : 0 - 0 // CHECK-NEXT: [[@LINE-1]]:16 -> [[@LINE+4]]:4 : 1 - // CHECK-NEXT: [[@LINE+3]]:4 -> {{[0-9]+}}:2 : 0 - - // FIXME: The below line is incorrect, it should be (0 - 1), but that's an existing bug with else ifs. - } else if .random() { // CHECK-NEXT: [[@LINE]]:13 -> [[@LINE]]:22 : 0 +func if_expr() -> Int { // CHECK: [[@LINE]]:23 -> {{[0-9]+}}:2 : 0 + if .random() { // CHECK-NEXT: [[@LINE]]:6 -> [[@LINE]]:15 : 0 + 0 // CHECK-NEXT: [[@LINE-1]]:16 -> [[@LINE+1]]:4 : 1 + } else if .random() { // CHECK-NEXT: [[@LINE]]:13 -> [[@LINE]]:22 : (0 - 1) 1 // CHECK-NEXT: [[@LINE-1]]:23 -> [[@LINE+1]]:4 : 2 - } else { // CHECK-NEXT: [[@LINE]]:4 -> {{[0-9]+}}:2 : 0 - - // FIXME: The below line is incorrect, it should be ((0 - 1) - 2), but that's an existing bug with else ifs. - 2 // CHECK-NEXT: [[@LINE-3]]:10 -> [[@LINE+4]]:4 : (0 - 2) - - // FIXME: Also incorrect - // CHECK-NEXT: [[@LINE+1]]:4 -> [[@LINE+2]]:2 : 0 + } else { // CHECK-NEXT: [[@LINE]]:10 -> [[@LINE+2]]:4 : ((0 - 1) - 2) + 2 } // CHECK-NEXT: } } diff --git a/test/Profiler/coverage_optimized_report.swift b/test/Profiler/coverage_optimized_report.swift index be958035f03d6..3520d932806ca 100644 --- a/test/Profiler/coverage_optimized_report.swift +++ b/test/Profiler/coverage_optimized_report.swift @@ -14,7 +14,7 @@ // REQUIRES: executable_test // REQUIRES: OS=macosx -// CHECK: "lines":{"count":9,"covered":6{{.*}}"functions":{"count":5,"covered":3 +// CHECK: "lines":{"count":9,"covered":5{{.*}}"functions":{"count":5,"covered":3 // The functions 'unused' and 'optimizedOut' will be optimized out, but // make sure we still emit coverage records for them, using name data emitted diff --git a/test/Profiler/coverage_property_wrapper_backing.swift b/test/Profiler/coverage_property_wrapper_backing.swift index 7cced4f1ba044..ea2652a76b33e 100644 --- a/test/Profiler/coverage_property_wrapper_backing.swift +++ b/test/Profiler/coverage_property_wrapper_backing.swift @@ -93,8 +93,7 @@ struct U { // CHECK-NEXT: [[@LINE-2]]:11 -> [[@LINE-2]]:40 : 0 // CHECK-NEXT: [[@LINE-3]]:14 -> [[@LINE-3]]:23 : 0 // CHECK-NEXT: [[@LINE-4]]:24 -> [[@LINE-4]]:29 : 1 - // CHECK-NEXT: [[@LINE-5]]:29 -> [[@LINE-5]]:40 : 0 - // CHECK-NEXT: [[@LINE-6]]:35 -> [[@LINE-6]]:40 : (0 - 1) + // CHECK-NEXT: [[@LINE-5]]:35 -> [[@LINE-5]]:40 : (0 - 1) // CHECK-NEXT: } }