Skip to content

Commit 5b2c6e5

Browse files
committed
use placement new so we don't destory an enum twice
1 parent c2e8ec9 commit 5b2c6e5

File tree

3 files changed

+30
-14
lines changed

3 files changed

+30
-14
lines changed

lib/PrintAsClang/DeclAndTypePrinter.cpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -466,9 +466,16 @@ class DeclAndTypePrinter::Implementation
466466
owningPrinter.outputLang);
467467
os << " get" << name << "() const {\n";
468468
os << " if (!is" << name << "()) abort();\n";
469-
os << " auto thisCopy = *this;\n";
469+
os << " alignas(";
470+
syntaxPrinter.printBaseName(ED);
471+
os << ") unsigned char buffer[sizeof(";
472+
syntaxPrinter.printBaseName(ED);
473+
os << ")];\n";
474+
os << " auto *thisCopy = new(buffer) ";
475+
syntaxPrinter.printBaseName(ED);
476+
os << "(*this);\n";
470477
os << " char * _Nonnull payloadFromDestruction = "
471-
"thisCopy._destructiveProjectEnumData();\n";
478+
"thisCopy->_destructiveProjectEnumData();\n";
472479
if (auto knownCxxType =
473480
owningPrinter.typeMapping.getKnownCxxTypeInfo(firstTypeDecl)) {
474481
os << " ";
@@ -480,7 +487,10 @@ class DeclAndTypePrinter::Implementation
480487
"memcpy(&result, payloadFromDestruction, sizeof(result));\n";
481488
os << " return result;\n";
482489
} else {
483-
os << " return " << cxx_synthesis::getCxxImplNamespaceName();
490+
os << " return ";
491+
syntaxPrinter.printModuleNamespaceQualifiersIfNeeded(
492+
firstTypeDecl->getModuleContext(), ED->getModuleContext());
493+
os << cxx_synthesis::getCxxImplNamespaceName();
484494
os << "::";
485495
ClangValueTypePrinter::printCxxImplClassName(os, firstTypeDecl);
486496
os << "::returnNewValue([&](char * _Nonnull result) {\n";

lib/PrintAsClang/PrintAsClang.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,8 @@ static void writePrologue(raw_ostream &out, ASTContext &ctx,
102102
out << "#include <cstdint>\n"
103103
"#include <cstddef>\n"
104104
"#include <cstdbool>\n"
105-
"#include <cstring>\n";
105+
"#include <cstring>\n"
106+
"#include <new>\n";
106107
out << "#include <stdlib.h>\n";
107108
out << "#if defined(_WIN32)\n#include <malloc.h>\n#endif\n";
108109
},

test/Interop/SwiftToCxx/enums/swift-enum-extract-payload.swift

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -111,24 +111,27 @@ public func makeUvw(_ x: Int) -> Uvw {
111111
// CHECK: class PrimitivePayload final {
112112
// CHECK: inline int64_t getX() const {
113113
// CHECK-NEXT: if (!isX()) abort();
114-
// CHECK-NEXT: auto thisCopy = *this;
115-
// CHECK-NEXT: char * _Nonnull payloadFromDestruction = thisCopy._destructiveProjectEnumData();
114+
// CHECK-NEXT: alignas(PrimitivePayload) unsigned char buffer[sizeof(PrimitivePayload)];
115+
// CHECK-NEXT: auto *thisCopy = new(buffer) PrimitivePayload(*this);
116+
// CHECK-NEXT: char * _Nonnull payloadFromDestruction = thisCopy->_destructiveProjectEnumData();
116117
// CHECK-NEXT: int64_t result;
117118
// CHECK-NEXT: memcpy(&result, payloadFromDestruction, sizeof(result));
118119
// CHECK-NEXT: return result;
119120
// CHECK-NEXT: }
120121
// CHECK: inline double getY() const {
121122
// CHECK-NEXT: if (!isY()) abort();
122-
// CHECK-NEXT: auto thisCopy = *this;
123-
// CHECK-NEXT: char * _Nonnull payloadFromDestruction = thisCopy._destructiveProjectEnumData();
123+
// CHECK-NEXT: alignas(PrimitivePayload) unsigned char buffer[sizeof(PrimitivePayload)];
124+
// CHECK-NEXT: auto *thisCopy = new(buffer) PrimitivePayload(*this);
125+
// CHECK-NEXT: char * _Nonnull payloadFromDestruction = thisCopy->_destructiveProjectEnumData();
124126
// CHECK-NEXT: double result;
125127
// CHECK-NEXT: memcpy(&result, payloadFromDestruction, sizeof(result));
126128
// CHECK-NEXT: return result;
127129
// CHECK-NEXT: }
128130
// CHECK: inline bool getZ() const {
129131
// CHECK-NEXT: if (!isZ()) abort();
130-
// CHECK-NEXT: auto thisCopy = *this;
131-
// CHECK-NEXT: char * _Nonnull payloadFromDestruction = thisCopy._destructiveProjectEnumData();
132+
// CHECK-NEXT: alignas(PrimitivePayload) unsigned char buffer[sizeof(PrimitivePayload)];
133+
// CHECK-NEXT: auto *thisCopy = new(buffer) PrimitivePayload(*this);
134+
// CHECK-NEXT: char * _Nonnull payloadFromDestruction = thisCopy->_destructiveProjectEnumData();
132135
// CHECK-NEXT: bool result;
133136
// CHECK-NEXT: memcpy(&result, payloadFromDestruction, sizeof(result));
134137
// CHECK-NEXT: return result;
@@ -173,16 +176,18 @@ public func makeUvw(_ x: Int) -> Uvw {
173176
// CHECK: class Xyz final {
174177
// CHECK: inline Foo getFirst() const {
175178
// CHECK-NEXT: if (!isFirst()) abort();
176-
// CHECK-NEXT: auto thisCopy = *this;
177-
// CHECK-NEXT: char * _Nonnull payloadFromDestruction = thisCopy._destructiveProjectEnumData();
179+
// CHECK-NEXT: alignas(Xyz) unsigned char buffer[sizeof(Xyz)];
180+
// CHECK-NEXT: auto *thisCopy = new(buffer) Xyz(*this);
181+
// CHECK-NEXT: char * _Nonnull payloadFromDestruction = thisCopy->_destructiveProjectEnumData();
178182
// CHECK-NEXT: return _impl::_impl_Foo::returnNewValue([&](char * _Nonnull result) {
179183
// CHECK-NEXT: _impl::_impl_Foo::initializeWithTake(result, payloadFromDestruction);
180184
// CHECK-NEXT: });
181185
// CHECK-NEXT: }
182186
// CHECK: inline Bar getThird() const {
183187
// CHECK-NEXT: if (!isThird()) abort();
184-
// CHECK-NEXT: auto thisCopy = *this;
185-
// CHECK-NEXT: char * _Nonnull payloadFromDestruction = thisCopy._destructiveProjectEnumData();
188+
// CHECK-NEXT: alignas(Xyz) unsigned char buffer[sizeof(Xyz)];
189+
// CHECK-NEXT: auto *thisCopy = new(buffer) Xyz(*this);
190+
// CHECK-NEXT: char * _Nonnull payloadFromDestruction = thisCopy->_destructiveProjectEnumData();
186191
// CHECK-NEXT: return _impl::_impl_Bar::returnNewValue([&](char * _Nonnull result) {
187192
// CHECK-NEXT: _impl::_impl_Bar::initializeWithTake(result, payloadFromDestruction);
188193
// CHECK-NEXT: });

0 commit comments

Comments
 (0)