Skip to content

SILGen: Fix crash when referencing dynamic Self from @convention(c) closure #28551

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

Merged
merged 3 commits into from
Dec 4, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions include/swift/AST/CaptureInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ class CaptureInfo {

ArrayRef<CapturedValue> getCaptures() const {
// FIXME: Ideally, everywhere that synthesizes a function should include
// its capture info.
// its capture info.
if (!hasBeenComputed())
return None;
return StorageAndFlags.getPointer()->getCaptures();
Expand All @@ -188,7 +188,7 @@ class CaptureInfo {
/// \returns true if the function captures any generic type parameters.
bool hasGenericParamCaptures() const {
// FIXME: Ideally, everywhere that synthesizes a function should include
// its capture info.
// its capture info.
if (!hasBeenComputed())
return false;
return StorageAndFlags.getInt().contains(Flags::HasGenericParamCaptures);
Expand All @@ -202,7 +202,7 @@ class CaptureInfo {
/// \returns the captured dynamic Self type, if any.
DynamicSelfType *getDynamicSelfType() const {
// FIXME: Ideally, everywhere that synthesizes a function should include
// its capture info.
// its capture info.
if (!hasBeenComputed())
return nullptr;
return StorageAndFlags.getPointer()->getDynamicSelfType();
Expand All @@ -214,7 +214,7 @@ class CaptureInfo {

OpaqueValueExpr *getOpaqueValue() const {
// FIXME: Ideally, everywhere that synthesizes a function should include
// its capture info.
// its capture info.
if (!hasBeenComputed())
return nullptr;
return StorageAndFlags.getPointer()->getOpaqueValue();
Expand Down
2 changes: 1 addition & 1 deletion include/swift/AST/DiagnosticsSIL.def
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ ERROR(unsupported_c_function_pointer_conversion,none,
ERROR(c_function_pointer_from_function_with_context,none,
"a C function pointer cannot be formed from a "
"%select{local function|closure}0 that captures "
"%select{context|generic parameters|dynamic Self type|<<error>}1",
"%select{context|generic parameters|dynamic Self type}1",
(bool, unsigned))

ERROR(objc_selector_malformed,none,"the type ObjectiveC.Selector is malformed",
Expand Down
17 changes: 7 additions & 10 deletions lib/SILGen/SILGenExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1550,25 +1550,22 @@ ManagedValue emitCFunctionPointer(SILGenFunction &SGF,
// C function pointers cannot capture anything from their context.
auto captures = SGF.SGM.Types.getLoweredLocalCaptures(constant);

if (captures.hasGenericParamCaptures() ||
if (!captures.getCaptures().empty() ||
captures.hasGenericParamCaptures() ||
captures.hasDynamicSelfCapture() ||
captures.hasLocalCaptures() ||
captures.hasOpaqueValueCapture()) {
unsigned kind;
if (captures.hasLocalCaptures())
kind = 0;
else if (captures.hasGenericParamCaptures())
unsigned kind = 0;
if (captures.hasGenericParamCaptures())
kind = 1;
else if (captures.hasLocalCaptures())
else if (captures.hasDynamicSelfCapture())
kind = 2;
else
kind = 3;
SGF.SGM.diagnose(expr->getLoc(),
diag::c_function_pointer_from_function_with_context,
/*closure*/ constant.hasClosureExpr(),
kind);

return SGF.emitUndef(constantInfo.getSILType());
auto loweredTy = SGF.getLoweredType(conversionExpr->getType());
return SGF.emitUndef(loweredTy);
}

return convertCFunctionSignature(
Expand Down
13 changes: 13 additions & 0 deletions test/IDE/print_swift_module.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -emit-module-path %t/print_swift_module.swiftmodule -emit-module-doc -emit-module-doc-path %t/print_swift_module.swiftdoc %s
// RUN: %target-swift-ide-test -print-module -print-interface -no-empty-line-between-members -module-to-print=print_swift_module -I %t -source-filename=%s > %t.syn.txt
// RUN: %target-swift-ide-test -print-module -access-filter-internal -no-empty-line-between-members -module-to-print=print_swift_module -I %t -source-filename=%s > %t.syn.internal.txt
// RUN: %FileCheck %s -check-prefix=CHECK1 < %t.syn.txt
// RUN: %FileCheck %s -check-prefix=CHECK2 < %t.syn.internal.txt

public protocol P1 {
/// foo1 comment from P1
Expand Down Expand Up @@ -53,3 +55,14 @@ public struct City {

// CHECK1: /// returnsAlias() comment
// CHECK1-NEXT: func returnsAlias() -> print_swift_module.Alias<Int>

// CHECK2: struct Event {
public struct Event {
public var start: Int
public var end: Int?
public var repeating: ((), Int?)
public var name = "untitled event"

// CHECK2: init(start: Int, end: Int? = nil, repeating: ((), Int?) = ((), nil), name: String = "untitled event")
}
// CHECK2: }
7 changes: 7 additions & 0 deletions test/SILGen/c_function_pointers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -105,3 +105,10 @@ func pointers_to_nested_local_functions_in_generics<T>(x: T) -> Int{
func capture_list_no_captures(x: Int) {
calls({ [x] in $0 }, 0) // expected-warning {{capture 'x' was never used}}
}

class Selfless {
func capture_dynamic_self() {
calls_no_args { _ = Self.self; return 0 }
// expected-error@-1 {{a C function pointer cannot be formed from a closure that captures dynamic Self type}}
}
}