Skip to content

Commit 6d16962

Browse files
[Interop] [SwiftToCxx] Using buffer to create an instance for either a type or an Error and fixing minor errors
1 parent 3f6351d commit 6d16962

File tree

2 files changed

+51
-22
lines changed

2 files changed

+51
-22
lines changed

lib/PrintAsClang/_SwiftCxxInteroperability.h

Lines changed: 49 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -195,16 +195,28 @@ template <class T> inline void *_Nonnull getOpaquePointer(T &value) {
195195

196196
} // namespace _impl
197197

198+
constexpr static std::size_t max(std::size_t a, std::size_t b) {
199+
return a > b ? a : b;
200+
}
201+
198202
/// The Expected class has either an error or an value.
199203
template<class T>
200204
class Expected {
201205
public:
202206

203207
/// Default
204-
constexpr Expected() { has_val = false; }
205-
constexpr Expected(const swift::Error& error_val) : err(error_val) { has_val = false; }
206-
constexpr Expected(T buf) {
207-
new (&buffer) T(buf);
208+
constexpr Expected() noexcept {
209+
new (&buffer) Error();
210+
has_val = false;
211+
}
212+
213+
constexpr Expected(const swift::Error& error_val) noexcept {
214+
new (&buffer) Error(error_val);
215+
has_val = false;
216+
}
217+
218+
constexpr Expected(const T &val) noexcept {
219+
new (&buffer) T(val);
208220
has_val = true;
209221
}
210222

@@ -213,38 +225,55 @@ class Expected {
213225
if (other.has_value())
214226
new (&buffer) T(other.value());
215227
else
216-
new (&err) Error(other.error());
228+
new (&buffer) Error(other.error());
217229

218230
has_val = other.has_value();
219231
}
232+
220233
/// Move
221234
// FIXME: Implement move semantics when move Swift values is possible
222235
constexpr Expected(Expected&&) noexcept { abort(); }
223236

224-
~Expected() noexcept { }
237+
~Expected() noexcept {
238+
if (has_value())
239+
reinterpret_cast<const T *>(buffer)->~T();
240+
else
241+
reinterpret_cast<swift::Error *>(buffer)->~Error();
242+
}
225243

226244
/// assignment
227-
constexpr auto operator=(Expected&& other) noexcept { auto temp = buffer; buffer = other.buffer; other.buffer = temp; }
245+
constexpr auto operator=(Expected&& other) noexcept = delete;
228246
constexpr auto operator=(Expected&) noexcept = delete;
229247

230248
/// For accessing T's members
231-
// precondition: has_value() == true
232-
constexpr T const *_Nonnull operator->() const noexcept { return reinterpret_cast<const T *>(buffer); }
249+
constexpr T const *_Nonnull operator->() const noexcept {
250+
if (!has_value())
251+
abort();
252+
return reinterpret_cast<const T *>(buffer);
253+
}
233254

234-
// precondition: has_value() == true
235-
constexpr T *_Nonnull operator->() noexcept { return reinterpret_cast<T *>(buffer); }
255+
constexpr T *_Nonnull operator->() noexcept {
256+
if (!has_value())
257+
abort();
258+
return reinterpret_cast<T *>(buffer);
259+
}
236260

237261
/// Getting reference to T
238-
// precondition: has_value() == true
239-
constexpr T const &operator*() const & noexcept { return reinterpret_cast<const T &>(buffer); }
262+
constexpr T const &operator*() const & noexcept {
263+
if (!has_value())
264+
abort();
265+
return reinterpret_cast<const T &>(buffer);
266+
}
240267

241-
// precondition: has_value() == true
242-
constexpr T &operator*() & noexcept { return reinterpret_cast<T &>(buffer); }
268+
constexpr T &operator*() & noexcept {
269+
if (!has_value())
270+
abort();
271+
return reinterpret_cast<T &>(buffer);
272+
}
243273

244274
constexpr explicit operator bool() const noexcept { return has_value(); }
245275

246276
// Get value, if not exists abort
247-
// FIXME: throw exception instead of abort?
248277
constexpr T const& value() const& {
249278
if (!has_value())
250279
abort();
@@ -261,19 +290,19 @@ class Expected {
261290
constexpr swift::Error const& error() const& {
262291
if (has_value())
263292
abort();
264-
return err;
293+
return reinterpret_cast<const swift::Error&>(buffer);
265294
}
295+
266296
constexpr swift::Error& error() & {
267297
if (has_value())
268298
abort();
269-
return err;
299+
return reinterpret_cast<swift::Error&>(buffer);
270300
}
271301

272302
constexpr bool has_value() const noexcept { return has_val; }
273303

274304
private:
275-
alignas(alignof(T)) char buffer[sizeof(T)];
276-
swift::Error err;
305+
alignas(max(alignof(T), alignof(swift::Error))) char buffer[max(sizeof(T), sizeof(swift::Error))];
277306
bool has_val;
278307
};
279308

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ int main() {
5656

5757
// Test Reference to T's members
5858
if (*testIntValue == 42)
59-
printf("Test Reference to T's members (const)\n");
59+
printf("Test Reference to T's members\n");
6060

6161
// Test bool operator
6262
if (testIntValue) {
@@ -103,7 +103,7 @@ int main() {
103103
// CHECK: Test Access to T's members (const)
104104
// CHECK-NEXT: Test Access to T's members
105105
// CHECK-NEXT: Test Reference to T's members (const)
106-
// CHECK-NEXT: Test Reference to T's members (const)
106+
// CHECK-NEXT: Test Reference to T's members
107107
// CHECK-NEXT: Test operator bool
108108
// CHECK-NEXT: Test get T's Value (const)
109109
// CHECK-NEXT: Test get T's Value

0 commit comments

Comments
 (0)