Skip to content

Commit 5371414

Browse files
authored
Merge pull request #62197 from Robertorosmaninho/cxx-interop/DynamicCastToSwiftErrorWithOptional
[Interop] [SwiftToCxx] Modify the swift::Error Dynamic Cast to return a Swift::Optional
2 parents 3617b76 + fdc1d0c commit 5371414

File tree

7 files changed

+104
-135
lines changed

7 files changed

+104
-135
lines changed

lib/PrintAsClang/PrintClangFunction.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1238,7 +1238,7 @@ void DeclAndTypeClangFunctionPrinter::printCxxThunkBody(
12381238
// Create the condition and the statement to throw an exception.
12391239
if (hasThrows) {
12401240
os << " if (opaqueError != nullptr)\n";
1241-
os << " throw (swift::Error(opaqueError));\n";
1241+
os << " throw (Swift::Error(opaqueError));\n";
12421242
}
12431243

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

lib/PrintAsClang/PrintSwiftToClangCoreScaffold.cpp

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -156,26 +156,6 @@ static void printTypeMetadataResponseType(SwiftToClangInteropContext &ctx,
156156
funcSig.parameterTypes[0]);
157157
}
158158

159-
void printCxxNaiveException(raw_ostream &os) {
160-
os << "/// Naive exception class that should be thrown\n";
161-
os << "class NaiveException : public swift::Error {\n";
162-
os << "public:\n";
163-
os << " inline NaiveException(const char * _Nonnull msg) noexcept : "
164-
<< "msg_(msg) { }\n";
165-
os << " inline NaiveException(NaiveException&& other) noexcept : "
166-
"msg_(other.msg_) { other.msg_ = nullptr; }\n";
167-
os << " inline ~NaiveException() noexcept { }\n";
168-
os << " void operator =(NaiveException&& other) noexcept { auto temp = msg_;"
169-
<< " msg_ = other.msg_; other.msg_ = temp; }\n";
170-
os << " void operator =(const NaiveException&) noexcept = delete;";
171-
os << "\n";
172-
os << " inline const char * _Nonnull getMessage() const noexcept { "
173-
<< "return(msg_); }\n";
174-
os << "private:\n";
175-
os << " const char * _Nonnull msg_;\n";
176-
os << "};\n";
177-
}
178-
179159
void printPrimitiveGenericTypeTraits(raw_ostream &os, ASTContext &astContext,
180160
PrimitiveTypeMapping &typeMapping,
181161
bool isCForwardDefinition) {
@@ -239,7 +219,6 @@ void swift::printSwiftToClangCoreScaffold(SwiftToClangInteropContext &ctx,
239219
/*isCForwardDefinition=*/true);
240220
});
241221
os << "\n";
242-
printCxxNaiveException(os);
243222
});
244223
os << "\n";
245224
// C++ only supports inline variables from C++17.

lib/PrintAsClang/_SwiftCxxInteroperability.h

Lines changed: 0 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -195,95 +195,6 @@ template <class T> inline void *_Nonnull getOpaquePointer(T &value) {
195195

196196
} // namespace _impl
197197

198-
extern "C" void *_Nonnull swift_errorRetain(void *_Nonnull swiftError) noexcept;
199-
200-
extern "C" void swift_errorRelease(void *_Nonnull swiftError) noexcept;
201-
202-
extern "C" int $ss5ErrorMp; // external global %swift.protocol, align 4
203-
204-
extern "C"
205-
const void * _Nullable
206-
swift_getTypeByMangledNameInContext(
207-
const char *_Nullable typeNameStart,
208-
size_t typeNameLength,
209-
const void *_Nullable context,
210-
const void *_Nullable const *_Nullable genericArgs) SWIFT_CALL;
211-
212-
extern "C" bool swift_dynamicCast(void *_Nullable dest, void *_Nullable src,
213-
const void *_Nullable srcType,
214-
const void * _Nullable targetType,
215-
uint32_t flags);
216-
217-
struct SymbolicP {
218-
alignas(2) uint8_t _1;
219-
uint32_t _2;
220-
uint8_t _3[2];
221-
uint8_t _4;
222-
} __attribute__((packed));
223-
224-
inline const void *_Nullable getErrorMetadata() {
225-
static swift::SymbolicP errorSymbol;
226-
static int *_Nonnull got_ss5ErrorMp = &$ss5ErrorMp;
227-
errorSymbol._1 = 2;
228-
errorSymbol._2 = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(&got_ss5ErrorMp) - reinterpret_cast<uintptr_t>(&errorSymbol._2));
229-
errorSymbol._3[0] = '_';
230-
errorSymbol._3[1] = 'p';
231-
errorSymbol._4 = 0;
232-
static_assert(sizeof(errorSymbol) == 8, "");
233-
auto charErrorSymbol = reinterpret_cast<const char *>(&errorSymbol);
234-
235-
const void *ptr2 =
236-
swift::swift_getTypeByMangledNameInContext(charErrorSymbol,
237-
sizeof(errorSymbol) - 1,
238-
nullptr, nullptr);
239-
return ptr2;
240-
}
241-
242-
class Error {
243-
public:
244-
Error() {}
245-
Error(void* _Nonnull swiftError) { opaqueValue = swiftError; }
246-
~Error() {
247-
if (opaqueValue)
248-
swift_errorRelease(opaqueValue);
249-
}
250-
void* _Nonnull getPointerToOpaquePointer() { return opaqueValue; }
251-
Error(Error &&other) : opaqueValue(other.opaqueValue) {
252-
other.opaqueValue = nullptr;
253-
}
254-
Error(const Error &other) {
255-
if (other.opaqueValue)
256-
swift_errorRetain(other.opaqueValue);
257-
opaqueValue = other.opaqueValue;
258-
}
259-
260-
// FIXME: Return a Swift::Optional instead.
261-
template<class T>
262-
T as() {
263-
alignas(alignof(T)) char buffer[sizeof(T)];
264-
const void *em = getErrorMetadata();
265-
void *ep = getPointerToOpaquePointer();
266-
auto metadata = swift::TypeMetadataTrait<T>::getTypeMetadata();
267-
268-
// Dynamic cast will release the error, so we need to retain it.
269-
swift::swift_errorRetain(ep);
270-
bool dynamicCast =
271-
swift::swift_dynamicCast(buffer, &ep, em, metadata,
272-
/*take on success destroy on failure*/ 6);
273-
274-
if (dynamicCast) {
275-
return swift::_impl::implClassFor<T>::type::returnNewValue([&](char *dest) {
276-
swift::_impl::implClassFor<T>::type::initializeWithTake(dest, buffer);
277-
});
278-
}
279-
abort();
280-
// FIXME: return nil.
281-
}
282-
283-
private:
284-
void * _Nonnull opaqueValue = nullptr;
285-
};
286-
287198
#pragma clang diagnostic pop
288199

289200
} // namespace swift

lib/PrintAsClang/_SwiftStdlibCxxOverlay.h

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,4 +91,92 @@ SWIFT_INLINE_THUNK cxxOverlay::IterationEndSentinel end(const Array<T> &) {
9191
return {};
9292
}
9393

94+
extern "C" void *_Nonnull swift_errorRetain(void *_Nonnull swiftError) noexcept;
95+
96+
extern "C" void swift_errorRelease(void *_Nonnull swiftError) noexcept;
97+
98+
extern "C" int $ss5ErrorMp; // external global %swift.protocol, align 4
99+
100+
extern "C" const void *_Nullable swift_getTypeByMangledNameInContext(
101+
const char *_Nullable typeNameStart, size_t typeNameLength,
102+
const void *_Nullable context,
103+
const void *_Nullable const *_Nullable genericArgs) SWIFT_CALL;
104+
105+
extern "C" bool swift_dynamicCast(void *_Nullable dest, void *_Nullable src,
106+
const void *_Nullable srcType,
107+
const void *_Nullable targetType,
108+
uint32_t flags);
109+
110+
struct SymbolicP {
111+
alignas(2) uint8_t _1;
112+
uint32_t _2;
113+
uint8_t _3[2];
114+
uint8_t _4;
115+
} __attribute__((packed));
116+
117+
inline const void *_Nullable getErrorMetadata() {
118+
static SymbolicP errorSymbol;
119+
static int *_Nonnull got_ss5ErrorMp = &$ss5ErrorMp;
120+
errorSymbol._1 = 2;
121+
errorSymbol._2 =
122+
static_cast<uint32_t>(reinterpret_cast<uintptr_t>(&got_ss5ErrorMp) -
123+
reinterpret_cast<uintptr_t>(&errorSymbol._2));
124+
errorSymbol._3[0] = '_';
125+
errorSymbol._3[1] = 'p';
126+
errorSymbol._4 = 0;
127+
static_assert(sizeof(errorSymbol) == 8, "");
128+
auto charErrorSymbol = reinterpret_cast<const char *>(&errorSymbol);
129+
130+
const void *ptr2 = swift_getTypeByMangledNameInContext(
131+
charErrorSymbol, sizeof(errorSymbol) - 1, nullptr, nullptr);
132+
return ptr2;
133+
}
134+
135+
class Error {
136+
public:
137+
Error() {}
138+
Error(void *_Nonnull swiftError) { opaqueValue = swiftError; }
139+
~Error() {
140+
if (opaqueValue)
141+
swift_errorRelease(opaqueValue);
142+
}
143+
void *_Nonnull getPointerToOpaquePointer() { return opaqueValue; }
144+
Error(Error &&other) : opaqueValue(other.opaqueValue) {
145+
other.opaqueValue = nullptr;
146+
}
147+
Error(const Error &other) {
148+
if (other.opaqueValue)
149+
swift_errorRetain(other.opaqueValue);
150+
opaqueValue = other.opaqueValue;
151+
}
152+
153+
template <class T>
154+
Swift::Optional<T> as() {
155+
alignas(alignof(T)) char buffer[sizeof(T)];
156+
const void *em = getErrorMetadata();
157+
void *ep = getPointerToOpaquePointer();
158+
auto metadata = swift::TypeMetadataTrait<T>::getTypeMetadata();
159+
160+
// Dynamic cast will release the error, so we need to retain it.
161+
swift_errorRetain(ep);
162+
bool dynamicCast =
163+
swift_dynamicCast(buffer, &ep, em, metadata,
164+
/*take on success destroy on failure*/ 6);
165+
166+
if (dynamicCast) {
167+
auto result = swift::_impl::implClassFor<T>::type::returnNewValue(
168+
[&](char *dest) {
169+
swift::_impl::implClassFor<T>::type::initializeWithTake(dest,
170+
buffer);
171+
});
172+
return Swift::Optional<T>::init(result);
173+
}
174+
175+
return Swift::Optional<T>::none();
176+
}
177+
178+
private:
179+
void *_Nonnull opaqueValue = nullptr;
180+
};
181+
94182
#endif

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

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -98,18 +98,6 @@
9898
// CHECK-NEXT: }
9999
// CHECK-NEXT: #endif
100100
// CHECK-EMPTY:
101-
// CHECK-NEXT: /// Naive exception class that should be thrown
102-
// CHECK-NEXT: class NaiveException : public swift::Error {
103-
// CHECK-NEXT: public:
104-
// CHECK-NEXT: inline NaiveException(const char * _Nonnull msg) noexcept : msg_(msg) { }
105-
// CHECK-NEXT: inline NaiveException(NaiveException&& other) noexcept : msg_(other.msg_) { other.msg_ = nullptr; }
106-
// CHECK-NEXT: inline ~NaiveException() noexcept { }
107-
// CHECK-NEXT: void operator =(NaiveException&& other) noexcept { auto temp = msg_; msg_ = other.msg_; other.msg_ = temp; }
108-
// CHECK-NEXT: void operator =(const NaiveException&) noexcept = delete;
109-
// CHECK-NEXT: inline const char * _Nonnull getMessage() const noexcept { return(msg_); }
110-
// CHECK-NEXT: private:
111-
// CHECK-NEXT: const char * _Nonnull msg_;
112-
// CHECK-NEXT: };
113101
// CHECK-EMPTY:
114102
// CHECK-NEXT: } // namespace _impl
115103
// CHECK-EMPTY:

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

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

3-
// RUN: %target-swift-frontend %S/swift-functions-errors.swift -typecheck -module-name Functions -clang-header-expose-decls=has-expose-attr -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 -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
66
// 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
@@ -25,24 +25,27 @@ int main() {
2525

2626
try {
2727
Functions::emptyThrowFunction();
28-
} catch (swift::Error& e) {
28+
} catch (Swift::Error& e) {
2929
printf("Exception\n");
3030
}
3131
try {
3232
Functions::throwFunction();
33-
} catch (swift::Error& e) {
34-
auto errorVal = e.as<Functions::NaiveErrors>();
33+
} catch (Swift::Error& e) {
34+
auto errorOpt = e.as<Functions::NaiveErrors>();
35+
assert(errorOpt.isSome());
36+
37+
auto errorVal = errorOpt.get();
3538
assert(errorVal == Functions::NaiveErrors::throwError);
3639
errorVal.getMessage();
3740
}
3841
try {
3942
Functions::throwFunctionWithReturn();
40-
} catch (swift::Error& e) {
43+
} catch (Swift::Error& e) {
4144
printf("Exception\n");
4245
}
4346
try {
4447
Functions::testDestroyedError();
45-
} catch(const swift::Error &e) { }
48+
} catch(const Swift::Error &e) { }
4649

4750
return 0;
4851
}

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

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

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

77
// CHECK-LABEL: namespace Functions __attribute__((swift_private)) {
88

@@ -31,7 +31,7 @@ public func emptyThrowFunction() throws { print("passEmptyThrowFunction") }
3131
// CHECK: void* _ctx = nullptr;
3232
// CHECK: _impl::$s9Functions18emptyThrowFunctionyyKF(_ctx, &opaqueError);
3333
// CHECK: if (opaqueError != nullptr)
34-
// CHECK: throw (swift::Error(opaqueError))
34+
// CHECK: throw (Swift::Error(opaqueError))
3535
// CHECK: }
3636

3737
class TestDestroyed {
@@ -53,7 +53,7 @@ public func testDestroyedError() throws { throw DestroyedError() }
5353
// CHECK: void* _ctx = nullptr;
5454
// CHECK: _impl::$s9Functions18testDestroyedErroryyKF(_ctx, &opaqueError);
5555
// CHECK: if (opaqueError != nullptr)
56-
// CHECK: throw (swift::Error(opaqueError))
56+
// CHECK: throw (Swift::Error(opaqueError))
5757
// CHECK: }
5858

5959
@_expose(Cxx)
@@ -67,7 +67,7 @@ public func throwFunction() throws {
6767
// CHECK: void* _ctx = nullptr;
6868
// CHECK: _impl::$s9Functions13throwFunctionyyKF(_ctx, &opaqueError);
6969
// CHECK: if (opaqueError != nullptr)
70-
// CHECK: throw (swift::Error(opaqueError))
70+
// CHECK: throw (Swift::Error(opaqueError))
7171
// CHECK: }
7272

7373
@_expose(Cxx)
@@ -82,6 +82,6 @@ public func throwFunctionWithReturn() throws -> Int {
8282
// CHECK: void* _ctx = nullptr;
8383
// CHECK: auto returnValue = _impl::$s9Functions23throwFunctionWithReturnSiyKF(_ctx, &opaqueError);
8484
// CHECK: if (opaqueError != nullptr)
85-
// CHECK: throw (swift::Error(opaqueError))
85+
// CHECK: throw (Swift::Error(opaqueError))
8686
// CHECK: return returnValue;
8787
// CHECK: }

0 commit comments

Comments
 (0)