Skip to content

Commit 1d37973

Browse files
committed
[interop][SwiftToCxx] do not expose functions / properties that throw without the experimental feature
1 parent 2dcbeb0 commit 1d37973

File tree

10 files changed

+64
-6
lines changed

10 files changed

+64
-6
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1619,6 +1619,8 @@ ERROR(expose_generic_decl_to_cxx,none,
16191619
"generic %0 %1 can not yet be exposed to C++", (DescriptiveDeclKind, ValueDecl *))
16201620
ERROR(expose_generic_requirement_to_cxx,none,
16211621
"generic requirements for %0 %1 can not yet be represented in C++", (DescriptiveDeclKind, ValueDecl *))
1622+
ERROR(expose_throwing_to_cxx,none,
1623+
"%0 %1 can not yet be represented in C++ as it may throw an error", (DescriptiveDeclKind, ValueDecl *))
16221624

16231625
ERROR(attr_methods_only,none,
16241626
"only methods can be declared %0", (DeclAttribute))

include/swift/AST/SwiftNameTranslation.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@ enum RepresentationError {
7070
UnrepresentableIsolatedInActor,
7171
UnrepresentableRequiresClientEmission,
7272
UnrepresentableGeneric,
73-
UnrepresentableGenericRequirements
73+
UnrepresentableGenericRequirements,
74+
UnrepresentableThrows
7475
};
7576

7677
struct DeclRepresentation {

include/swift/Basic/Features.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,9 @@ EXPERIMENTAL_FEATURE(RuntimeDiscoverableAttrs, false)
174174
/// signatures.
175175
EXPERIMENTAL_FEATURE(ImportSymbolicCXXDecls, false)
176176

177+
/// Generate bindings for functions that 'throw' in the C++ section of the generated Clang header.
178+
EXPERIMENTAL_FEATURE(GenerateBindingsForThrowingFunctionsInCXX, false)
179+
177180
#undef EXPERIMENTAL_FEATURE
178181
#undef UPCOMING_FEATURE
179182
#undef SUPPRESSIBLE_LANGUAGE_FEATURE

lib/AST/ASTPrinter.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3170,6 +3170,10 @@ static bool usesFeatureBuiltinMacros(Decl *decl) {
31703170

31713171
static bool usesFeatureImportSymbolicCXXDecls(Decl *decl) { return false; }
31723172

3173+
static bool usesFeatureGenerateBindingsForThrowingFunctionsInCXX(Decl *decl) {
3174+
return false;
3175+
}
3176+
31733177
static bool usesFeatureFreestandingExpressionMacros(Decl *decl) {
31743178
auto macro = dyn_cast<MacroDecl>(decl);
31753179
if (!macro)

lib/AST/SwiftNameTranslation.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,10 @@ swift::cxx_translation::getDeclRepresentation(const ValueDecl *VD) {
179179
if (auto *AFD = dyn_cast<AbstractFunctionDecl>(VD)) {
180180
if (AFD->hasAsync())
181181
return {Unsupported, UnrepresentableAsync};
182+
if (AFD->hasThrows() &&
183+
!AFD->getASTContext().LangOpts.hasFeature(
184+
Feature::GenerateBindingsForThrowingFunctionsInCXX))
185+
return {Unsupported, UnrepresentableThrows};
182186
// Don't expose @_alwaysEmitIntoClient functions as they require their
183187
// bodies to be emitted into client.
184188
if (AFD->getAttrs().hasAttribute<AlwaysEmitIntoClientAttr>())
@@ -194,6 +198,13 @@ swift::cxx_translation::getDeclRepresentation(const ValueDecl *VD) {
194198
typeDecl->getGenericSignature().getCanonicalSignature();
195199
}
196200
}
201+
if (const auto *varDecl = dyn_cast<VarDecl>(VD)) {
202+
// Check if any property accessor throws, do not expose it in that case.
203+
for (const auto *accessor : varDecl->getAllAccessors()) {
204+
if (accessor->hasThrows())
205+
return {Unsupported, UnrepresentableThrows};
206+
}
207+
}
197208
// Generic requirements are not yet supported in C++.
198209
if (genericSignature && !genericSignature->getRequirements().empty())
199210
return {Unsupported, UnrepresentableGenericRequirements};

lib/Sema/TypeCheckAttr.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2004,6 +2004,10 @@ void AttributeChecker::visitExposeAttr(ExposeAttr *attr) {
20042004
diagnose(attr->getLocation(), diag::expose_generic_requirement_to_cxx,
20052005
VD->getDescriptiveKind(), VD);
20062006
break;
2007+
case UnrepresentableThrows:
2008+
diagnose(attr->getLocation(), diag::expose_throwing_to_cxx,
2009+
VD->getDescriptiveKind(), VD);
2010+
break;
20072011
}
20082012
}
20092013

test/Interop/SwiftToCxx/functions/swift-expected-execution.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
// RUN: %empty-directory(%t)
22

3-
// RUN: %target-swift-frontend %S/swift-functions-errors.swift -typecheck -module-name Functions -Xcc -fno-exceptions -enable-experimental-cxx-interop -clang-header-expose-decls=has-expose-attr-or-stdlib -emit-clang-header-path %t/functions.h
3+
// RUN: %target-swift-frontend %S/swift-functions-errors.swift -typecheck -module-name Functions -Xcc -fno-exceptions -enable-experimental-cxx-interop -clang-header-expose-decls=has-expose-attr-or-stdlib -enable-experimental-feature GenerateBindingsForThrowingFunctionsInCXX -emit-clang-header-path %t/functions.h
44

55
// RUN: %target-interop-build-clangxx -c %s -I %t -fno-exceptions -o %t/swift-expected-execution.o
6-
// RUN: %target-interop-build-swift %S/swift-functions-errors.swift -o %t/swift-expected-execution -Xlinker %t/swift-expected-execution.o -module-name Functions -Xfrontend -entry-point-function-name -Xfrontend swiftMain
6+
// RUN: %target-interop-build-swift %S/swift-functions-errors.swift -o %t/swift-expected-execution -Xlinker %t/swift-expected-execution.o -module-name Functions -Xfrontend -entry-point-function-name -Xfrontend swiftMain -enable-experimental-feature GenerateBindingsForThrowingFunctionsInCXX
77

88
// RUN: %target-codesign %t/swift-expected-execution
99
// RUN: %target-run %t/swift-expected-execution | %FileCheck %s
@@ -12,6 +12,9 @@
1212
// UNSUPPORTED: OS=windows-msvc
1313
// UNSUPPORTED: CPU=arm64e
1414

15+
// for experimental feature GenerateBindingsForThrowingFunctionsInCXX:
16+
// REQUIRES: asserts
17+
1518
#include <cassert>
1619
#include <cstdio>
1720
#include "functions.h"

test/Interop/SwiftToCxx/functions/swift-functions-errors-execution.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
// RUN: %empty-directory(%t)
22

3-
// RUN: %target-swift-frontend %S/swift-functions-errors.swift -typecheck -module-name Functions -enable-experimental-cxx-interop -clang-header-expose-decls=has-expose-attr-or-stdlib -emit-clang-header-path %t/functions.h
3+
// RUN: %target-swift-frontend %S/swift-functions-errors.swift -typecheck -module-name Functions -enable-experimental-cxx-interop -clang-header-expose-decls=has-expose-attr-or-stdlib -enable-experimental-feature GenerateBindingsForThrowingFunctionsInCXX -emit-clang-header-path %t/functions.h
44

55
// RUN: %target-interop-build-clangxx -c %s -I %t -o %t/swift-functions-errors-execution.o
6-
// RUN: %target-interop-build-swift %S/swift-functions-errors.swift -o %t/swift-functions-errors-execution -Xlinker %t/swift-functions-errors-execution.o -module-name Functions -Xfrontend -entry-point-function-name -Xfrontend swiftMain
6+
// RUN: %target-interop-build-swift %S/swift-functions-errors.swift -o %t/swift-functions-errors-execution -Xlinker %t/swift-functions-errors-execution.o -module-name Functions -Xfrontend -entry-point-function-name -Xfrontend swiftMain -enable-experimental-feature GenerateBindingsForThrowingFunctionsInCXX
77

88
// RUN: %target-codesign %t/swift-functions-errors-execution
99
// RUN: %target-run %t/swift-functions-errors-execution | %FileCheck %s
@@ -14,6 +14,9 @@
1414
// rdar://102167469
1515
// UNSUPPORTED: CPU=arm64e
1616

17+
// for experimental feature GenerateBindingsForThrowingFunctionsInCXX:
18+
// REQUIRES: asserts
19+
1720
#include <cassert>
1821
#include <cstdio>
1922
#include "functions.h"

test/Interop/SwiftToCxx/functions/swift-functions-errors.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
// RUN: %empty-directory(%t)
2-
// RUN: %target-swift-frontend %s -typecheck -module-name Functions -enable-experimental-cxx-interop -clang-header-expose-decls=has-expose-attr-or-stdlib -emit-clang-header-path %t/functions.h
2+
// RUN: %target-swift-frontend %s -typecheck -module-name Functions -enable-experimental-cxx-interop -clang-header-expose-decls=has-expose-attr-or-stdlib -enable-experimental-feature GenerateBindingsForThrowingFunctionsInCXX -emit-clang-header-path %t/functions.h
33
// RUN: %FileCheck %s < %t/functions.h
44

55
// RUN: %check-interop-cxx-header-in-clang(%t/functions.h -DSWIFT_CXX_INTEROP_HIDE_STL_OVERLAY -Wno-unused-function)
66

7+
// for experimental feature GenerateBindingsForThrowingFunctionsInCXX:
8+
// REQUIRES: asserts
9+
710
// CHECK-LABEL: namespace Functions __attribute__((swift_private)) SWIFT_SYMBOL_MODULE("Functions") {
811

912
// CHECK-LABEL: namespace _impl {

test/Interop/SwiftToCxx/unsupported/unsupported-funcs-in-cxx.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,34 @@
66
// RUN: %FileCheck %s < %t/header.h
77

88
// CHECK-NOT: unsupported
9+
// CHECK: HasMethods
910
// CHECK: supported
1011

1112
public func supported() {}
1213

1314
@_expose(Cxx) // expected-error {{global function 'unsupportedAEIC()' can not be exposed to C++ as it requires code to be emitted into client}}
1415
@_alwaysEmitIntoClient
1516
public func unsupportedAEIC() {}
17+
18+
@_expose(Cxx) // expected-error {{global function 'unsupportedThrows()' can not yet be represented in C++ as it may throw an error}}
19+
public func unsupportedThrows() throws {}
20+
21+
@_expose(Cxx)
22+
public struct HasMethods {
23+
let x: Int
24+
25+
@_expose(Cxx) // expected-error {{instance method 'unsupportedThrowsMethod()' can not yet be represented in C++ as it may throw an error}}
26+
public func unsupportedThrowsMethod() throws {}
27+
28+
@_expose(Cxx) // expected-error {{initializer 'init()' can not yet be represented in C++ as it may throw an error}}
29+
public init() throws {
30+
self.x = 0
31+
}
32+
33+
@_expose(Cxx) // expected-error {{property 'unsupportedProp' can not yet be represented in C++ as it may throw an error}}
34+
public var unsupportedProp: Int {
35+
get throws {
36+
return 42
37+
}
38+
}
39+
}

0 commit comments

Comments
 (0)