Skip to content

Commit e98d908

Browse files
authored
Merge pull request #60858 from Robertorosmaninho/cxx-interop/SwiftToCxxErrorHandling
[SwiftToCxx] Including Cxx representation of Swift's Error
2 parents 2efc0f6 + 68bfbdd commit e98d908

File tree

6 files changed

+65
-15
lines changed

6 files changed

+65
-15
lines changed

lib/PrintAsClang/PrintClangFunction.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -527,7 +527,7 @@ ClangRepresentation DeclAndTypeClangFunctionPrinter::printFunctionSignature(
527527
}
528528
} else if (param.role == AdditionalParam::Role::Error) {
529529
os << "SWIFT_ERROR_RESULT ";
530-
os << "void ** _error";
530+
os << "void * _Nullable * _Nullable _error";
531531
} else if (param.role == AdditionalParam::Role::GenericRequirement) {
532532
os << "void * _Nonnull ";
533533
if (param.genericRequirement->Protocol)
@@ -787,7 +787,7 @@ void DeclAndTypeClangFunctionPrinter::printCxxThunkBody(
787787
// Create the condition and the statement to throw an exception.
788788
if (hasThrows) {
789789
os << " if (opaqueError != nullptr)\n";
790-
os << " throw (swift::_impl::NaiveException(\"Exception\"));\n";
790+
os << " throw (swift::Error(opaqueError));\n";
791791
}
792792

793793
// Return the function result value if it doesn't throw.

lib/PrintAsClang/PrintSwiftToClangCoreScaffold.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ static void printTypeMetadataResponseType(SwiftToClangInteropContext &ctx,
158158

159159
void printCxxNaiveException(raw_ostream &os) {
160160
os << "/// Naive exception class that should be thrown\n";
161-
os << "class NaiveException {\n";
161+
os << "class NaiveException : public swift::Error {\n";
162162
os << "public:\n";
163163
os << " inline NaiveException(const char * _Nonnull msg) noexcept : "
164164
<< "msg_(msg) { }\n";

stdlib/public/SwiftShims/_SwiftCxxInteroperability.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,32 @@ template <class T> inline void *_Nonnull getOpaquePointer(T &value) {
176176

177177
} // namespace _impl
178178

179+
extern "C" void *_Nonnull swift_errorRetain(void *_Nonnull swiftError) noexcept;
180+
181+
extern "C" void swift_errorRelease(void *_Nonnull swiftError) noexcept;
182+
183+
class Error {
184+
public:
185+
Error() {}
186+
Error(void* _Nonnull swiftError) { opaqueValue = swiftError; }
187+
~Error() {
188+
if (opaqueValue)
189+
swift_errorRelease(opaqueValue);
190+
}
191+
void* _Nonnull getPointerToOpaquePointer() { return opaqueValue; }
192+
Error(Error &&other) : opaqueValue(other.opaqueValue) {
193+
other.opaqueValue = nullptr;
194+
}
195+
Error(const Error &other) {
196+
if (other.opaqueValue)
197+
swift_errorRetain(other.opaqueValue);
198+
opaqueValue = other.opaqueValue;
199+
}
200+
201+
private:
202+
void * _Nonnull opaqueValue = nullptr;
203+
};
204+
179205
#pragma clang diagnostic pop
180206

181207
} // namespace swift

test/Interop/SwiftToCxx/core/swift-impl-defs-in-cxx.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@
9999
// CHECK-NEXT: #endif
100100
// CHECK-EMPTY:
101101
// CHECK-NEXT: /// Naive exception class that should be thrown
102-
// CHECK-NEXT: class NaiveException {
102+
// CHECK-NEXT: class NaiveException : public swift::Error {
103103
// CHECK-NEXT: public:
104104
// CHECK-NEXT: inline NaiveException(const char * _Nonnull msg) noexcept : msg_(msg) { }
105105
// CHECK-NEXT: inline NaiveException(NaiveException&& other) noexcept : msg_(other.msg_) { other.msg_ = nullptr; }

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

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,22 @@ int main() {
2121

2222
try {
2323
Functions::emptyThrowFunction();
24-
} catch (swift::_impl::NaiveException& e) {
25-
printf("%s\n", e.getMessage());
24+
} catch (swift::Error& e) {
25+
printf("Exception\n");
2626
}
2727
try {
2828
Functions::throwFunction();
29-
} catch (swift::_impl::NaiveException& e) {
30-
printf("%s\n", e.getMessage());
29+
} catch (swift::Error& e) {
30+
printf("Exception\n");
3131
}
3232
try {
3333
Functions::throwFunctionWithReturn();
34-
} catch (swift::_impl::NaiveException& e) {
35-
printf("%s\n", e.getMessage());
34+
} catch (swift::Error& e) {
35+
printf("Exception\n");
3636
}
37+
try {
38+
Functions::testDestroyedError();
39+
} catch(const swift::Error &e) { }
3740

3841
return 0;
3942
}
@@ -43,3 +46,4 @@ int main() {
4346
// CHECK-NEXT: Exception
4447
// CHECK-NEXT: passThrowFunctionWithReturn
4548
// CHECK-NEXT: Exception
49+
// CHECK-NEXT: Test destroyed

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

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88

99
// CHECK-LABEL: namespace _impl {
1010

11-
// CHECK: SWIFT_EXTERN void $s9Functions18emptyThrowFunctionyyKF(SWIFT_CONTEXT void * _Nonnull _self, SWIFT_ERROR_RESULT void ** _error) SWIFT_CALL; // emptyThrowFunction()
12-
// CHECK: SWIFT_EXTERN void $s9Functions13throwFunctionyyKF(SWIFT_CONTEXT void * _Nonnull _self, SWIFT_ERROR_RESULT void ** _error) SWIFT_CALL; // throwFunction()
11+
// CHECK: SWIFT_EXTERN void $s9Functions18emptyThrowFunctionyyKF(SWIFT_CONTEXT void * _Nonnull _self, SWIFT_ERROR_RESULT void * _Nullable * _Nullable _error) SWIFT_CALL; // emptyThrowFunction()
12+
// CHECK: SWIFT_EXTERN void $s9Functions13throwFunctionyyKF(SWIFT_CONTEXT void * _Nonnull _self, SWIFT_ERROR_RESULT void * _Nullable * _Nullable _error) SWIFT_CALL; // throwFunction()
1313

1414
// CHECK: }
1515

@@ -25,7 +25,27 @@ public func emptyThrowFunction() throws { print("passEmptyThrowFunction") }
2525
// CHECK: void* self = nullptr;
2626
// CHECK: _impl::$s9Functions18emptyThrowFunctionyyKF(self, &opaqueError);
2727
// CHECK: if (opaqueError != nullptr)
28-
// CHECK: throw (swift::_impl::NaiveException("Exception"));
28+
// CHECK: throw (swift::Error(opaqueError))
29+
// CHECK: }
30+
31+
class TestDestroyed {
32+
deinit {
33+
print("Test destroyed")
34+
}
35+
}
36+
37+
public struct DestroyedError : Error {
38+
let t = TestDestroyed()
39+
}
40+
41+
public func testDestroyedError() throws { throw DestroyedError() }
42+
43+
// CHECK: inline void testDestroyedError() {
44+
// CHECK: void* opaqueError = nullptr;
45+
// CHECK: void* self = nullptr;
46+
// CHECK: _impl::$s9Functions18testDestroyedErroryyKF(self, &opaqueError);
47+
// CHECK: if (opaqueError != nullptr)
48+
// CHECK: throw (swift::Error(opaqueError))
2949
// CHECK: }
3050

3151
public func throwFunction() throws {
@@ -38,7 +58,7 @@ public func throwFunction() throws {
3858
// CHECK: void* self = nullptr;
3959
// CHECK: _impl::$s9Functions13throwFunctionyyKF(self, &opaqueError);
4060
// CHECK: if (opaqueError != nullptr)
41-
// CHECK: throw (swift::_impl::NaiveException("Exception"));
61+
// CHECK: throw (swift::Error(opaqueError))
4262
// CHECK: }
4363

4464
public func throwFunctionWithReturn() throws -> Int {
@@ -52,6 +72,6 @@ public func throwFunctionWithReturn() throws -> Int {
5272
// CHECK: void* self = nullptr;
5373
// CHECK: auto returnValue = _impl::$s9Functions23throwFunctionWithReturnSiyKF(self, &opaqueError);
5474
// CHECK: if (opaqueError != nullptr)
55-
// CHECK: throw (swift::_impl::NaiveException("Exception"));
75+
// CHECK: throw (swift::Error(opaqueError))
5676
// CHECK: return returnValue;
5777
// CHECK: }

0 commit comments

Comments
 (0)