Skip to content

Commit 702189a

Browse files
authored
Work around a VC++ bug in util::overload (#7742)
1 parent dde1ab2 commit 702189a

File tree

3 files changed

+19
-25
lines changed

3 files changed

+19
-25
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
-----------
1717

1818
### Internals
19-
* None.
19+
* Work around a bug in VC++ that resulted in runtime errors when running the tests in a debug build (#[7741](https://github.com/realm/realm-core/issues/7741)).
2020

2121
----------------------------------------------
2222

src/realm/sync/changeset.cpp

Lines changed: 9 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -44,30 +44,15 @@ InternString Changeset::find_string(StringData string) const noexcept
4444

4545
PrimaryKey Changeset::get_key(const Instruction::PrimaryKey& key) const noexcept
4646
{
47-
// we do not use the expected `mpark::visit(overload...` because in MSVC 2019 this
48-
// code produces a segfault for something that works on other compilers.
49-
// See https://github.com/realm/realm-core/issues/4624
50-
if (const auto int64_ptr = mpark::get_if<int64_t>(&key)) {
51-
return *int64_ptr;
52-
}
53-
else if (const auto intern_string_ptr = mpark::get_if<InternString>(&key)) {
54-
return this->get_string(*intern_string_ptr);
55-
}
56-
else if (const auto monostate_ptr = mpark::get_if<mpark::monostate>(&key)) {
57-
return *monostate_ptr;
58-
}
59-
else if (const auto global_key_ptr = mpark::get_if<GlobalKey>(&key)) {
60-
return *global_key_ptr;
61-
}
62-
else if (const auto oid_ptr = mpark::get_if<ObjectId>(&key)) {
63-
return *oid_ptr;
64-
}
65-
else if (const auto uuid_ptr = mpark::get_if<UUID>(&key)) {
66-
return *uuid_ptr;
67-
}
68-
else {
69-
REALM_UNREACHABLE(); // unhandled primary key type
70-
}
47+
return mpark::visit(overload{
48+
[this](InternString str) -> PrimaryKey {
49+
return get_string(str);
50+
},
51+
[](auto otherwise) -> PrimaryKey {
52+
return otherwise;
53+
},
54+
},
55+
key);
7156
}
7257

7358
bool Changeset::operator==(const Changeset& that) const noexcept

src/realm/util/overload.hpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,15 @@ namespace realm::util {
2323
template <class... Ts>
2424
struct overload : Ts... {
2525
using Ts::operator()...;
26+
#ifdef _MSC_VER
27+
// https://developercommunity.visualstudio.com/t/runtime-stack-corruption-using-stdvisit/346200
28+
// A bug in VC++'s Empty Base Optimization causes it to compute the wrong
29+
// size if both the type and the last base class have zero size. This
30+
// results in the stack pointer being adjusted incorrectly if the final
31+
// lambda passed to overload has no captures. Making overload non-zero size
32+
// prevents this.
33+
char dummy = 0;
34+
#endif
2635
};
2736
template <class... Ts>
2837
overload(Ts...) -> overload<Ts...>;

0 commit comments

Comments
 (0)