Skip to content

Commit 30fc84c

Browse files
authored
Merge pull request #84103 from egorzhdan/egorzhdan/std-optional-noncopyable
[cxx-interop] Avoid trying to instantiate copy constructor of `std::optional<NonCopyable>`
2 parents f244c8f + 124055a commit 30fc84c

File tree

3 files changed

+25
-0
lines changed

3 files changed

+25
-0
lines changed

lib/ClangImporter/ImportDecl.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3026,8 +3026,17 @@ namespace {
30263026
decl->getIdentifier() &&
30273027
(decl->getName() == "tzdb" || decl->getName() == "time_zone_link" ||
30283028
decl->getName() == "__compressed_pair" ||
3029+
decl->getName() == "__optional_copy_assign_base" || // libc++
3030+
decl->getName() == "__optional_move_assign_base" || // libc++
30293031
decl->getName() == "time_zone"))
30303032
return nullptr;
3033+
// Bail if this is one of the base types of std::optional. Those types are
3034+
// mixins that are not designed to be used directly.
3035+
if (decl->getDeclContext()->isNamespace() && decl->isInStdNamespace() &&
3036+
decl->getIdentifier() &&
3037+
(decl->getName() == "_Optional_payload_base" ||
3038+
decl->getName() == "_Optional_payload"))
3039+
return nullptr;
30313040

30323041
auto &clangSema = Impl.getClangSema();
30333042
// Make Clang define any implicit constructors it may need (copy,

test/Interop/Cxx/stdlib/Inputs/std-optional.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,14 @@ struct HasConstexprCtor {
1717
};
1818
using StdOptionalHasConstexprCtor = std::optional<HasConstexprCtor>;
1919

20+
struct HasDeletedCopyCtor {
21+
int value;
22+
HasDeletedCopyCtor(int value) : value(value) {}
23+
HasDeletedCopyCtor(const HasDeletedCopyCtor &other) = delete;
24+
HasDeletedCopyCtor(HasDeletedCopyCtor &&other) = default;
25+
};
26+
using StdOptionalHasDeletedCopyCtor = std::optional<HasDeletedCopyCtor>;
27+
2028
struct HasDeletedMoveCtor {
2129
int value;
2230
HasDeletedMoveCtor(int value) : value(value) {}
@@ -29,7 +37,12 @@ inline StdOptionalInt getNonNilOptional() { return {123}; }
2937

3038
inline StdOptionalInt getNilOptional() { return {std::nullopt}; }
3139

40+
inline StdOptionalHasDeletedCopyCtor getNonNilOptionalHasDeletedCopyCtor() {
41+
return StdOptionalHasDeletedCopyCtor(HasDeletedCopyCtor(654));
42+
}
43+
3244
inline bool takesOptionalInt(std::optional<int> arg) { return (bool)arg; }
3345
inline bool takesOptionalString(std::optional<std::string> arg) { return (bool)arg; }
46+
inline bool takesOptionalHasDeletedCopyCtor(std::optional<HasDeletedCopyCtor> arg) { return (bool)arg; }
3447

3548
#endif // TEST_INTEROP_CXX_STDLIB_INPUTS_STD_OPTIONAL_H

test/Interop/Cxx/stdlib/use-std-optional.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ StdOptionalTestSuite.test("pointee") {
2525
modifiedOpt.pointee = 777
2626
expectEqual(777, modifiedOpt.pointee)
2727
#endif
28+
29+
let nonNilOptNonCopyable = getNonNilOptionalHasDeletedCopyCtor()
30+
expectEqual(654, nonNilOptNonCopyable.pointee.value)
2831
}
2932

3033
StdOptionalTestSuite.test("std::optional => Swift.Optional") {

0 commit comments

Comments
 (0)