diff --git a/lib/Sema/TypeCheckPattern.cpp b/lib/Sema/TypeCheckPattern.cpp index 87e0a39c13651..be0d57fc247e4 100644 --- a/lib/Sema/TypeCheckPattern.cpp +++ b/lib/Sema/TypeCheckPattern.cpp @@ -768,13 +768,27 @@ ExprPatternMatchRequest::evaluate(Evaluator &evaluator, DeclNameLoc(EP->getLoc())); matchOp->setImplicit(); + auto subExpr = EP->getSubExpr(); + + // Pull off the outer "unsafe" expression. + UnsafeExpr *unsafeExpr = dyn_cast(subExpr); + if (unsafeExpr) { + subExpr = unsafeExpr->getSubExpr(); + } + // Note we use getEndLoc here to have the BinaryExpr source range be the same // as the expr pattern source range. auto *matchVarRef = new (ctx) DeclRefExpr(matchVar, DeclNameLoc(EP->getEndLoc()), /*Implicit=*/true); - auto *matchCall = BinaryExpr::create(ctx, EP->getSubExpr(), matchOp, + Expr *matchCall = BinaryExpr::create(ctx, subExpr, matchOp, matchVarRef, /*implicit*/ true); + + // If there was an "unsafe", put it outside of the match call. + if (unsafeExpr) { + matchCall = UnsafeExpr::createImplicit(ctx, unsafeExpr->getLoc(), matchCall); + } + return {matchVar, matchCall}; } diff --git a/lib/Sema/TypeCheckUnsafe.cpp b/lib/Sema/TypeCheckUnsafe.cpp index d2bd110cc9df4..833d4097de8d3 100644 --- a/lib/Sema/TypeCheckUnsafe.cpp +++ b/lib/Sema/TypeCheckUnsafe.cpp @@ -165,20 +165,20 @@ void swift::diagnoseUnsafeUse(const UnsafeUse &use) { ctx.Diags.diagnose( loc, diag::note_unsafe_call_decl_argument_indexed, - calleeDecl, argumentIndex, paramType) + calleeDecl, argumentIndex, argument->getType()) .highlight(argument->getSourceRange()); } else { ctx.Diags.diagnose( loc, diag::note_unsafe_call_decl_argument_named, - calleeDecl, argumentName, paramType) + calleeDecl, argumentName, argument->getType()) .highlight(argument->getSourceRange()); } } else { ctx.Diags.diagnose( loc, diag::note_unsafe_call_argument_indexed, - argumentIndex, paramType) + argumentIndex, argument->getType()) .highlight(argument->getSourceRange()); } diff --git a/test/Unsafe/safe.swift b/test/Unsafe/safe.swift index acaea12e5bd68..4a22410611345 100644 --- a/test/Unsafe/safe.swift +++ b/test/Unsafe/safe.swift @@ -317,3 +317,35 @@ extension Slice { } } } + +@unsafe enum SomeEnum { + case first + case second +} + +@unsafe var someEnumValue: SomeEnum = unsafe .first + +func testSwitch(se: SomeEnum) { + switch unsafe se { + case unsafe someEnumValue: break + default: break + } + + switch unsafe se { + case someEnumValue: break + // expected-warning@-1{{expression uses unsafe constructs but is not marked with 'unsafe'}}{{8-8=unsafe }} + // expected-note@-2{{argument #0 in call to operator function '~=' has unsafe type 'SomeEnum'}} + // expected-note@-3{{argument #1 in call to operator function '~=' has unsafe type 'SomeEnum'}} + // expected-note@-4{{reference to unsafe type 'SomeEnum'}} + // expected-note@-5{{reference to unsafe var 'someEnumValue'}} + // expected-note@-6{{reference to let '$match' involves unsafe type 'SomeEnum'}} + default: break + } + + // expected-note@+2{{reference to parameter 'se' involves unsafe type 'SomeEnum'}} + // expected-warning@+1{{expression uses unsafe constructs but is not marked with 'unsafe'}}{{10-10=unsafe }} + switch se { + case unsafe someEnumValue: break + default: break + } +} diff --git a/test/Unsafe/unsafe.swift b/test/Unsafe/unsafe.swift index ce7971c959741..2d45881942906 100644 --- a/test/Unsafe/unsafe.swift +++ b/test/Unsafe/unsafe.swift @@ -49,7 +49,7 @@ extension ConformsToMultiP: MultiP { // expected-note@-1{{unsafe type 'UnsafeSuper' cannot satisfy safe associated type 'Ptr'}} @unsafe func f() -> UnsafeSuper { .init() // expected-warning{{expression uses unsafe constructs but is not marked with 'unsafe'}} - // expected-note@-1{{argument 'self' in call to initializer 'init' has unsafe type 'UnsafeSuper'}} + // expected-note@-1{{argument 'self' in call to initializer 'init' has unsafe type 'UnsafeSuper.Type'}} } } diff --git a/test/Unsafe/unsafe_stdlib.swift b/test/Unsafe/unsafe_stdlib.swift index bd74b13a4d260..5d824ec138ae4 100644 --- a/test/Unsafe/unsafe_stdlib.swift +++ b/test/Unsafe/unsafe_stdlib.swift @@ -9,7 +9,7 @@ func test( ) { var array = [1, 2, 3] // expected-warning@+2{{expression uses unsafe constructs but is not marked with 'unsafe'}}{{3-3=unsafe }} - // expected-note@+1{{argument #0 in call to instance method 'withUnsafeBufferPointer' has unsafe type '(UnsafeBufferPointer) throws(E) -> R'}} + // expected-note@+1{{argument #0 in call to instance method 'withUnsafeBufferPointer' has unsafe type '(UnsafeBufferPointer) -> ()'}} array.withUnsafeBufferPointer{ buffer in // expected-warning@+1{{expression uses unsafe constructs but is not marked with 'unsafe'}}{{5-5=unsafe }} print(buffer) // expected-note{{reference to parameter 'buffer' involves unsafe type 'UnsafeBufferPointer'}}