Skip to content

Commit b15c6a5

Browse files
Implementing a naive exception to be thrown in C++ if an Error is thrown in Swift
Creating new Interop - SwiftToCxx test
1 parent 4e1a1b8 commit b15c6a5

File tree

5 files changed

+98
-5
lines changed

5 files changed

+98
-5
lines changed

lib/PrintAsClang/PrintClangFunction.cpp

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -433,9 +433,29 @@ void DeclAndTypeClangFunctionPrinter::printCxxThunkBody(
433433
}
434434

435435
// Primitive values are returned directly without any conversions.
436-
os << " return ";
436+
// Assign the function return value to a variable if the function can throw.
437+
if (!resultTy->isVoid() && hasThrows)
438+
os << " auto returnValue = ";
439+
// If the function doesn't have a return value just call it.
440+
else if (resultTy->isVoid() && hasThrows)
441+
os << " ";
442+
// If the function can't throw just return its value result.
443+
else if (!hasThrows)
444+
os << " return ";
437445
printCallToCFunc(/*additionalParam=*/None);
438446
os << ";\n";
447+
448+
// Create the condition and the statement to throw an exception.
449+
if (hasThrows) {
450+
os << " if (opaqueError != nullptr)\n";
451+
os << " throw (swift::_impl::NaiveException(\"Exception\"));\n";
452+
}
453+
454+
// Return the function result value if it doesn't throw.
455+
if (!resultTy->isVoid() && hasThrows) {
456+
os << "\n";
457+
os << "return returnValue;\n";
458+
}
439459
}
440460

441461
void DeclAndTypeClangFunctionPrinter::printCxxMethod(

lib/PrintAsClang/PrintSwiftToClangCoreScaffold.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,27 @@ static void printSwiftResilientStorageClass(raw_ostream &os) {
210210
os << "};\n";
211211
}
212212

213+
void printCxxNaiveException(raw_ostream &os) {
214+
os << "\n";
215+
os << "/// Naive exception class that should be thrown\n";
216+
os << "class NaiveException {\n";
217+
os << "public:\n";
218+
os << " inline NaiveException(const char * _Nonnull msg) noexcept : "
219+
<< "msg_(msg) { }\n";
220+
os << " inline NaiveException(NaiveException&& other) noexcept : "
221+
"msg_(other.msg_) { other.msg_ = nullptr; }\n";
222+
os << " inline ~NaiveException() noexcept { }\n";
223+
os << " void operator =(NaiveException&& other) noexcept { auto temp = msg_;"
224+
<< " msg_ = other.msg_; other.msg_ = temp; }\n";
225+
os << " void operator =(const NaiveException&) noexcept = delete;";
226+
os << "\n";
227+
os << " inline const char * _Nonnull getMessage() const noexcept { "
228+
<< "return(msg_); }\n";
229+
os << "private:\n";
230+
os << " const char * _Nonnull msg_;\n";
231+
os << "};\n";
232+
}
233+
213234
void swift::printSwiftToClangCoreScaffold(SwiftToClangInteropContext &ctx,
214235
PrimitiveTypeMapping &typeMapping,
215236
raw_ostream &os) {
@@ -226,6 +247,7 @@ void swift::printSwiftToClangCoreScaffold(SwiftToClangInteropContext &ctx,
226247
printOpaqueAllocFee(os);
227248
os << "\n";
228249
printSwiftResilientStorageClass(os);
250+
printCxxNaiveException(os);
229251
});
230252
});
231253
}

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,19 @@
106106
// CHECK-NEXT: char * _Nullable storage;
107107
// CHECK-NEXT: };
108108
// CHECK-EMPTY:
109+
// CHECK-NEXT: /// Naive exception class that should be thrown
110+
// CHECK-NEXT: class NaiveException {
111+
// CHECK-NEXT: public:
112+
// CHECK-NEXT: inline NaiveException(const char * _Nonnull msg) noexcept : msg_(msg) { }
113+
// CHECK-NEXT: inline NaiveException(NaiveException&& other) noexcept : msg_(other.msg_) { other.msg_ = nullptr; }
114+
// CHECK-NEXT: inline ~NaiveException() noexcept { }
115+
// CHECK-NEXT: void operator =(NaiveException&& other) noexcept { auto temp = msg_; msg_ = other.msg_; other.msg_ = temp; }
116+
// CHECK-NEXT: void operator =(const NaiveException&) noexcept = delete;
117+
// CHECK-NEXT: inline const char * _Nonnull getMessage() const noexcept { return(msg_); }
118+
// CHECK-NEXT: private:
119+
// CHECK-NEXT: const char * _Nonnull msg_;
120+
// CHECK-NEXT: };
121+
// CHECK-EMPTY:
109122
// CHECK-NEXT: } // namespace _impl
110123
// CHECK-EMPTY:
111124
// CHECK-EMPTY:

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

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,35 @@
1111
// REQUIRES: executable_test
1212

1313
#include <cassert>
14+
#include <iostream>
1415
#include "functions.h"
1516

1617
int main() {
1718
static_assert(!noexcept(Functions::emptyThrowFunction()), "noexcept function");
1819
static_assert(!noexcept(Functions::throwFunction()), "noexcept function");
20+
static_assert(!noexcept(Functions::throwFunctionWithReturn()), "noexcept function");
21+
22+
try {
23+
Functions::emptyThrowFunction();
24+
} catch (swift::_impl::NaiveException& e) {
25+
std::cout << e.getMessage() << "\n";
26+
}
27+
try {
28+
Functions::throwFunction();
29+
} catch (swift::_impl::NaiveException& e) {
30+
std::cout << e.getMessage() << "\n";
31+
}
32+
try {
33+
Functions::throwFunctionWithReturn();
34+
} catch (swift::_impl::NaiveException& e) {
35+
std::cout << e.getMessage() << "\n";
36+
}
1937

20-
Functions::emptyThrowFunction();
21-
Functions::throwFunction();
2238
return 0;
2339
}
2440

2541
// CHECK: passEmptyThrowFunction
2642
// CHECK-NEXT: passThrowFunction
43+
// CHECK-NEXT: Exception
44+
// CHECK-NEXT: passThrowFunctionWithReturn
45+
// CHECK-NEXT: Exception

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

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@ public func emptyThrowFunction() throws { print("passEmptyThrowFunction") }
2323
// CHECK: inline void emptyThrowFunction() {
2424
// CHECK: void* opaqueError = nullptr;
2525
// CHECK: void* self = nullptr;
26-
// CHECK: return _impl::$s9Functions18emptyThrowFunctionyyKF(self, &opaqueError);
26+
// CHECK: _impl::$s9Functions18emptyThrowFunctionyyKF(self, &opaqueError);
27+
// CHECK: if (opaqueError != nullptr)
28+
// CHECK: throw (swift::_impl::NaiveException("Exception"));
2729
// CHECK: }
2830

2931
public func throwFunction() throws {
@@ -34,5 +36,22 @@ public func throwFunction() throws {
3436
// CHECK: inline void throwFunction() {
3537
// CHECK: void* opaqueError = nullptr;
3638
// CHECK: void* self = nullptr;
37-
// CHECK: return _impl::$s9Functions13throwFunctionyyKF(self, &opaqueError);
39+
// CHECK: _impl::$s9Functions13throwFunctionyyKF(self, &opaqueError);
40+
// CHECK: if (opaqueError != nullptr)
41+
// CHECK: throw (swift::_impl::NaiveException("Exception"));
3842
// CHECK: }
43+
44+
public func throwFunctionWithReturn() throws -> Int {
45+
print("passThrowFunctionWithReturn")
46+
throw NaiveErrors.returnError
47+
return 0
48+
}
49+
50+
// CHECK: inline swift::Int throwFunctionWithReturn() SWIFT_WARN_UNUSED_RESULT {
51+
// CHECK: void* opaqueError = nullptr;
52+
// CHECK: void* self = nullptr;
53+
// CHECK: auto returnValue = _impl::$s9Functions23throwFunctionWithReturnSiyKF(self, &opaqueError);
54+
// CHECK: if (opaqueError != nullptr)
55+
// CHECK: throw (swift::_impl::NaiveException("Exception"));
56+
// CHECK: return returnValue;
57+
// CHECK: }

0 commit comments

Comments
 (0)