From 0e97be35f91ac1bb8ee01b647c6f7ef263324036 Mon Sep 17 00:00:00 2001 From: Russell Yanofsky Date: Thu, 17 Dec 2020 16:56:07 -0500 Subject: [PATCH] Avoid depending on argument default constructors CTransaction default constructor was removed in faac31521bb7ecbf999541cf918d3750ff589de4 https://github.com/bitcoin/bitcoin/pull/20588 which exposed two places where libmultiprocess was inadvertently assuming default constructors were defined. In both places, it would never actually call the default constructor at runtime, just rely on it being present during compile time code generation. In the first case, compiler would fail while trying to figure out the type of `std::invoke_result_t` where EmplaceFn called `make_shared()`. This was fixed by just the moving expression into an unexpanded template method. In the second case code was calling Optional::emplace() to default-initialize CTransaction& output-arguments. It was fixed by moving into a constexpr-if that would be known to be false for output arguments at compile time. --- include/mp/proxy-types.h | 31 ++++++++++++------------------- 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/include/mp/proxy-types.h b/include/mp/proxy-types.h index 92bb578..743b210 100644 --- a/include/mp/proxy-types.h +++ b/include/mp/proxy-types.h @@ -189,25 +189,14 @@ struct ReadDestEmplace template void update(UpdateFn&& update_fn) { - update(std::forward(update_fn), Priority<1>()); - } - - template >>, UpdateFn>> - void update(UpdateFn&& update_fn, Priority<1>) - { - update_fn(construct()); - } - - template - void update(UpdateFn&& update_fn, Priority<0>) - { - std::remove_cv_t temp; - update_fn(temp); - construct(std::move(temp)); + if constexpr (std::is_const_v>>) { + std::remove_cv_t temp; + update_fn(temp); + construct(std::move(temp)); + } else { + update_fn(construct()); + } } - EmplaceFn& m_emplace_fn; }; @@ -1073,7 +1062,11 @@ void DefaultPassField(TypeList, ServerContext& server_context, Fn&& f param.emplace(std::forward(args)...); return *param; })); - if (!param) param.emplace(); + if constexpr (Accessor::in) { + assert(param); + } else { + if (!param) param.emplace(); + } fn.invoke(server_context, std::forward(args)..., static_cast(*param)); auto&& results = server_context.call_context.getResults(); MaybeBuildField(std::integral_constant(), TypeList(), invoke_context,