Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SR-7446] Code coverage generation using the Swift 4.1 toolchain doesn't reach conditional code paths in init methods #49989

Closed
weichsel opened this issue Apr 16, 2018 · 4 comments
Assignees
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. code coverage Area → source tooling: code coverage compiler The Swift compiler in itself regression swift 4.1

Comments

@weichsel
Copy link

Previous ID SR-7446
Radar rdar://problem/39460313
Original Reporter @weichsel
Type Bug
Status Resolved
Resolution Done

Attachment: Download

Environment

Version 9.3 (9E145)

Swift 4.1

Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels Bug, 4.1Regression, CodeCoverage
Assignee @vedantk
Priority Medium

md5: db109c5ce197c124399547fb2436272a

Issue Description:

Since upgrading to Xcode 9.3/Swift 4.1, I noticed that code coverage percentage dropped in several of my projects.

The bug seems to occur when I use conditional code within an initializer:

init(name: String, age: Int, role: Role) {
    self.name = name
    self.age = age

    if self.age >= 18 {
        self.ofAge = true
    } else {
        self.ofAge = false
    }

    switch role {
    case .designer:
        self.tool = "Photoshop"
    case .engineer:
        self.tool = "Xcode"
    case .tester:
        self.tool = "Mail"
    }
}

Neither the if/else branches nor the switch cases are counted towards line coverage when compiling with Xcode 9.3 and "Gather coverage" turned on.

I wrote test cases (see attached project "Codepath.zip") that exercise the code paths in question and verified their execution with the debugger.
Older Xcode versions or the swift-4.0.3-RELEASE-osx toolchain from swift.org report correct percentages when I enable code coverage in the Test phase of the scheme.

I also tested the behaviour with a command line tool (see attached project "codepath-cli.zip") and

xcrun swiftc -profile-generate -profile-coverage-mapping main.swift
./main
xcrun llvm-profdata merge -o testprof.profdata default.profraw
xcrun llvm-cov show ./main -instr-profile=testprof.profdata main.swift

When using Xcode 9.3's default toolchain, conditional code within the initializer is not reached. When using the 4.0.3 final toolchain, all conditional code is counted correctly (at least once).

The test CLI tool project contains xcrun-based scripts to generate & show coverage for the Xcode default toolchain (showCoverageSwift41.sh) and the final 4.0.3 toolchain (showCoverageSwift403).

@belkadan
Copy link
Contributor

Bizarre. @vedantk, have you seen this before?

@vedantk
Copy link
Member

vedantk commented Apr 16, 2018

No, this is unexpected. The coverage mappings look correct, but the basic block counters in the profile data are wrong:

main.swift:$S4main6PersonC4name3age4roleACSS_SiAC4RoleOtcfC:
Hash: 0x0000000000000000
Counters: 6
Function count: 3
Block counts: [0, 0, 0, 0, 0]

@vedantk
Copy link
Member

vedantk commented Apr 16, 2018

It looks like there's a delegating constructor named "$S4main6PersonC4name3age4roleACSS_SiAC4RoleOtcfC". It calls "$S4main6PersonC4name3age4roleACSS_SiAC4RoleOtcfc", which does all of the work.

The delegating constructor increments its own function execution count, but ignores the 5 other counters it's associated with. Meanwhile the callee doesn't appear to be instrumented.

// Person.__allocating_init(name:age:role:)
sil hidden @$S4main6PersonC4name3age4roleACSS_SiAC4RoleOtcfC : $@convention(method) (@owned String, Int, Person.Role, @thick Person.Type) -> @owned Person {
// %0                                             // user: %6
// %1                                             // user: %6
// %2                                             // user: %6
bb0(%0 : $String, %1 : $Int, %2 : $Person.Role, %3 : $@thick Person.Type):
  %4 = alloc_ref $Person                          // user: %6
  // function_ref Person.init(name:age:role:)
  %5 = function_ref @$S4main6PersonC4name3age4roleACSS_SiAC4RoleOtcfc : $@convention(method) (@owned String, Int, Person.Role, @owned Person) -> @owned Person // user: %6
  %6 = apply %5(%0, %1, %2, %4) : $@convention(method) (@owned String, Int, Person.Role, @owned Person) -> @owned Person // user: %12
  %7 = string_literal utf8 "main.swift:$S4main6PersonC4name3age4roleACSS_SiAC4RoleOtcfC" // user: %11
  %8 = integer_literal $Builtin.Int64, 0          // user: %11
  %9 = integer_literal $Builtin.Int32, 6          // user: %11
  %10 = integer_literal $Builtin.Int32, 0         // user: %11
  %11 = builtin "int_instrprof_increment"(%7 : $Builtin.RawPointer, %8 : $Builtin.Int64, %9 : $Builtin.Int32, %10 : $Builtin.Int32) : $() 
  return %6 : $Person                             // id: %12
} // end sil function '$S4main6PersonC4name3age4roleACSS_SiAC4RoleOtcfC'

@vedantk
Copy link
Member

vedantk commented Apr 18, 2018

Fixed in swift PR #15966.

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. code coverage Area → source tooling: code coverage compiler The Swift compiler in itself regression swift 4.1
Projects
None yet
Development

No branches or pull requests

4 participants