blob: be8260068d6ebc9c6208563f60de3ed019e1d201 [file] [log] [blame]
// RUN: %target-swift-frontend -emit-sil -primary-file %s -o /dev/null -verify
func ifFalse() -> Int {
if false { // expected-note {{always evaluates to false}}
return 0 // expected-warning {{will never be executed}}
} else {
return 1
}
}
func ifTrue() -> Int {
_ = 0
if true { // expected-note {{always evaluates to true}}
return 1
}
return 0 // expected-warning {{will never be executed}}
}
func testUnreachableIfBranch() -> Int {
let a = 2
let c: Int
if a < 2 { // expected-note {{condition always evaluates to false}}
c = 3 // expected-warning {{will never be executed}}
} else {
c = 4
}
return c
}
func testUnreachableIfBranch2() -> Int {
let a = 2
let c: Int
if a > 2 { // expected-note {{condition always evaluates to false}}
c = 3 // expected-warning {{will never be executed}}
} else {
c = 4
}
return c
}
func testUnreachableElseBranch() -> Int {
let a = 2
let c: Int
if a == 2 { // expected-note {{condition always evaluates to true}}
c = 3
} else {
c = 4 // expected-warning {{will never be executed}}
}
return c
}
// FIXME: False Negative: <rdar://39516135>. No warnings are produced here
// as the statements along the unreachable branches are marked implicit.
// Unreachable code analysis suppresses warnings in such cases.
func testQuestionMarkOperator() -> Int {
let a = 2
let c: Int
c = (a < 2) ? 3 : 4
return c
}
// Work-around <rdar://problem/17687851> by ensuring there is
// something that appears to be user code in unreachable blocks.
func userCode() {}
func whileTrue() {
var x = 0
while true { // expected-note {{always evaluates to true}}
x += 1
}
userCode() // expected-warning {{will never be executed}}
}
func whileTrueSilent() {
while true {
}
} // no warning!
func whileTrueReachable(_ v: Int) -> () {
var x = 0
while true {
if v == 0 {
break
}
x += 1
}
x -= 1
}
func whileTrueTwoPredecessorsEliminated() -> () {
var x = 0
while (true) { // expected-note {{always evaluates to true}}
if false {
break
}
x += 1
}
userCode() // expected-warning {{will never be executed}}
}
func unreachableBranch() -> Int {
if false { // expected-note {{always evaluates to false}}
// FIXME: It'd be nice if the warning were on 'if true' instead of the
// body.
if true {
return 0 // expected-warning {{will never be executed}}
}
} else {
return 1
}
}
// We should not report unreachable user code inside inlined transparent function.
@_transparent
func ifTrueTransparent(_ b: Bool) -> Int {
_ = 0
if b {
return 1
}
return 0
}
func testIfTrueTransparent() {
_ = ifTrueTransparent(true) // no-warning
_ = ifTrueTransparent(false) // no-warning
}
// We should not report unreachable user code inside generic instantiations.
// TODO: This test should start failing after we add support for generic
// specialization in SIL. To fix it, add generic instantiation detection
// within the DeadCodeElimination pass to address the corresponding FIXME note.
protocol HavingGetCond {
func getCond() -> Bool
}
struct ReturnsTrue : HavingGetCond {
func getCond() -> Bool { return true }
}
struct ReturnsOpaque : HavingGetCond {
var b: Bool
func getCond() -> Bool { return b }
}
func ifTrueGeneric<T : HavingGetCond>(_ x: T) -> Int {
if x.getCond() {
return 1
}
return 0
}
func testIfTrueGeneric(_ b1: ReturnsOpaque, b2: ReturnsTrue) {
_ = ifTrueGeneric(b1) // no-warning
_ = ifTrueGeneric(b2) // no-warning
}
// Test switch_enum folding/diagnostic.
enum X {
case One
case Two
case Three
}
func testSwitchEnum(_ xi: Int) -> Int {
var x = xi
let cond: X = .Two
switch cond { // expected-warning {{switch condition evaluates to a constant}}
case .One:
userCode() // expected-note {{will never be executed}}
case .Two:
x -= 1
case .Three:
x -= 1
}
switch cond { // no warning
default:
x += 1
}
switch cond { // expected-warning{{switch condition evaluates to a constant}}
case .Two:
x += 1
default:
userCode() // expected-note{{will never be executed}}
}
switch cond { // expected-warning{{switch condition evaluates to a constant}}
case .One:
userCode() // expected-note{{will never be executed}}
default:
x -= 1
}
return x
}
@_silgen_name("exit") func exit() -> Never
func reachableThroughNonFoldedPredecessor(fn: @autoclosure () -> Bool = false) {
if !_fastPath(fn()) {
exit()
}
var _: Int = 0 // no warning
}
func intConstantTest() -> Int{
let y: Int = 1
if y == 1 { // expected-note {{condition always evaluates to true}}
return y
}
return 1 // expected-warning {{will never be executed}}
}
func intConstantTest2() -> Int{
let y:Int = 1
let x:Int = y
if x != 1 { // expected-note {{condition always evaluates to false}}
return y // expected-warning {{will never be executed}}
}
return 3
}
func test_single_statement_closure(_ fn:() -> ()) {}
test_single_statement_closure() {
exit() // no-warning
}
class C { }
class Super {
var s = C()
deinit { // no-warning
}
}
class D : Super {
var c = C()
deinit { // no-warning
exit()
}
}
// <rdar://problem/20097963> incorrect DI diagnostic in unreachable code
enum r20097963Test {
case A
case B
}
class r20097963MyClass {
func testStr(_ t: r20097963Test) -> String {
let str: String
switch t {
case .A:
str = "A"
case .B:
str = "B"
default: // expected-warning {{default will never be executed}}
str = "unknown" // Should not be rejected.
}
return str
}
}
func die() -> Never { die() } // expected-warning {{all paths through this function will call itself}}
func testGuard(_ a : Int) {
guard case 4 = a else { } // expected-error {{'guard' body must not fall through, consider using a 'return' or 'throw'}}
guard case 4 = a else { return } // ok
guard case 4 = a else { die() } // ok
guard case 4 = a else { fatalError("baaad") } // ok
for _ in 0...100 {
guard case 4 = a else { continue } // ok
}
}
func testFailingCast(_ s:String) -> Int {
// There should be no notes or warnings about a call to a noreturn function, because we do not expose
// how casts are lowered.
return s as! Int // expected-warning {{cast from 'String' to unrelated type 'Int' always fails}}
}
enum MyError : Error { case A }
func raise() throws -> Never { throw MyError.A }
func test_raise_1() throws -> Int {
try raise()
}
func test_raise_2() throws -> Int {
try raise() // expected-note {{a call to a never-returning function}}
try raise() // expected-warning {{will never be executed}}
}
// If a guaranteed self call requires cleanup, don't warn about
// release instructions
struct Algol {
var x: [UInt8]
func fail() throws -> Never { throw MyError.A }
mutating func blah() throws -> Int {
try fail() // no-warning
}
}
class Lisp {
func fail() throws -> Never { throw MyError.A }
}
func transform<Scheme : Lisp>(_ s: Scheme) throws {
try s.fail() // no-warning
}
func deferNoReturn() throws {
defer {
_ = Lisp() // no-warning
}
die()
}
func deferTryNoReturn() throws {
defer {
_ = Lisp() // no-warning
}
try raise()
}
func noReturnInDefer() {
defer { // expected-warning {{'defer' statement before end of scope always executes immediately}}{{3-8=do}}
_ = Lisp()
die() // expected-note {{a call to a never-returning function}}
die() // expected-warning {{will never be executed}}
}
}
while true {
}
// no warning!
// SR-1010 - rdar://25278336 - Spurious "will never be executed" warnings when building standard library
struct SR1010<T> {
var a : T
}
extension SR1010 {
@available(*, unavailable, message: "use the 'enumerated()' method on the sequence")
init(_ base: Int) {
fatalError("unavailable function can't be called")
}
}
// More spurious 'will never be executed' warnings
struct FailingStruct {
init?(x: ()) {
fatalError("gotcha")
}
}
class FailingClass {
init?(x: ()) {
fatalError("gotcha")
}
convenience init?(y: ()) {
fatalError("gotcha")
}
}
// <https://bugs.swift.org/browse/SR-2729>
// We should not report unreachable code inside protocol witness thunks
protocol Fooable {
init()
func foo() -> Never
}
struct Foo: Fooable {
init() { // no-warning
fatalError()
}
func foo() -> Never { // no-warning
while true {}
}
}
// We should not report unreachable code inside vtable thunks
class Base {
required init(x: Int) {
fatalError()
}
func foo(x: Int) -> Never {
while true {}
}
}
class Derived : Base {
required init(x: Int?) {
fatalError()
}
override func foo(x: Int?) -> Never {
while true {}
}
}
// Inout writeback
func takesInOut(value: inout SillyStruct) -> Never {
while true {}
}
struct SillyStruct {
mutating func mutatingMethod() -> Never {
takesInOut(value: &self)
}
}
// This triggers various problems
public func genericMightBeNever<R>(
_ body: () -> R) -> R {
while true {}
}
func sillyGenericExample() -> Never {
return genericMightBeNever {
return genericMightBeNever {
return fatalError()
}
}
}
// https://bugs.swift.org/browse/SR-7472
protocol P {
static var theThing: Self { get }
}
extension Never : P {
static var theThing: Never { return fatalError() }
}
func test<T: P>(_ type: T.Type) -> T {
return type.theThing
}
func f(i: Int?) {
guard i != nil else { Never.theThing }
guard i != nil else { test(Never.self) }
}