-
Notifications
You must be signed in to change notification settings - Fork 37.4k
Add bitcoin-{node,gui} to release binaries for IPC #31802
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. Code Coverage & BenchmarksFor details see: https://corecheck.dev/bitcoin/bitcoin/pulls/31802. ReviewsSee the guideline for information on the review process.
If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update. ConflictsReviewers, this pull request conflicts with the following ones:
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first. |
ef1e5b0
to
527a77e
Compare
Some chatter from IRC:
|
f43ff56
to
63dffe1
Compare
63dffe1
to
1cb3ff9
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code review ACK 7ecf6bb. Since last review rebased, enabled openbsd support by updating capnp, renamed variable and dropped whitespace changes, and avoided c includes to fix tidy modernize-deprecated-headers errors
This causes IPC binaries (bitcoin-node, bitcoin-gui) to be included in releases. The effect on CI is that this causes more depends builds to build IPC binaries, but still the only build running functional tests with them is the i686_multiprocess one. Except for Windows.
The bitcoin-node binary is built on all platforms which have multiprocess enabled, but for functional tests it's only used in CentOS native (depends) job. The next commit will also add a non-depends job.
Install capnp on non-depends CI jobs. Use the bitcoin-node binary in the macOS native non-depends job. Co-authored-by: Ryan Ofsky <[email protected]>
Co-authored-by: fanquake <[email protected]>
Rebased after #32760 (only change is dropping that commit). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code review ACK 5a66729. No change other than rebase and dropping base commit
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK 5a66729
Since you are renaming "multiprocess" to "ipc" in some places and you are also renaming 00_setup_env_i686_multiprocess.sh
to 00_setup_env_i686_no_multiprocess.sh
maybe 00_setup_env_i686_no_ipc.sh
would be a better new name of the file?
The last commit refactor: modernize deprecated ipc headers
is fine, but I am not sure why it is needed in this PR since those (old) .h
includes were not introduced in this PR. Is there not the same problem in master
? Or maybe tidy did not look at files in src/ipc/
before? If yes, then maybe that commit should be first, before the one that makes tidy check src/ipc/
, so that all intermediate commits are good.
If you want it to be bisect-nice, I'd guess you'd have to set |
Indeed that's why I didn't move it up initially. With this many CI changes it's hard to be bisect friendly to that level anyway. @vasild if I need to retouch I'll move that commit up and rename some more multiprocess things to ipc. |
This PR needs release notes. Note that the Tidy job here is passing, even though it's generating output (which also seems like a bug?). That should be addressed, to either fix any issues or suppress any false-positives; otherwise it's going to make the tidy output unusable. i.e (https://cirrus-ci.com/task/6552721135763456): Details
[02:41:41.544] [706/706][83.5s] clang-tidy-20 -p=/ci_container_base/ci/scratch/build-x86_64-pc-linux-gnu -quiet -load=/tidy-build/libbitcoin-tidy.so /ci_container_base/ci/scratch/build-x86_64-pc-linux-gnu/src/ipc/libmultiprocess/test/mp/test/foo.capnp.proxy-server.c++
[02:41:41.544] /ci_container_base/src/ipc/libmultiprocess/include/mp/proxy-types.h:134:5: warning: Address of stack memory associated with temporary object of type '(lambda at /ci_container_base/src/ipc/libmultiprocess/include/mp/proxy-types.h:134:51)' is still referred to by a temporary object on the stack upon returning to the caller. This will be a dangling reference [clang-analyzer-core.StackAddressEscape]
[02:41:41.544] 134 | return ReadDestEmplace{TypeList<LocalType>(), [&](auto&&... args) -> decltype(auto) {
[02:41:41.544] | ^
[02:41:41.544] /ci_container_base/ci/scratch/build-x86_64-pc-linux-gnu/src/ipc/libmultiprocess/test/mp/test/foo.capnp.proxy-server.c++:41:12: note: Calling 'serverInvoke<mp::ProxyServer<mp::test::messages::FooInterface>, capnp::CallContext<mp::test::messages::FooInterface::PassCustomParams, mp::test::messages::FooInterface::PassCustomResults>, mp::ServerField<1, mp::Accessor<mp::foo_fields::Arg, 17>, mp::ServerRet<mp::Accessor<mp::foo_fields::Result, 18>, mp::ServerCall>>>'
[02:41:41.544] 41 | return serverInvoke(*this, call_context, MakeServerField<1, Accessor<foo_fields::Arg, FIELD_IN | FIELD_BOXED>>(Make<ServerRet, Accessor<foo_fields::Result, FIELD_OUT | FIELD_BOXED>>(ServerCall())));
[02:41:41.544] | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] /ci_container_base/src/ipc/libmultiprocess/include/mp/proxy-types.h:704:16: note: Calling 'ReplaceVoid<(lambda at /ci_container_base/src/ipc/libmultiprocess/include/mp/proxy-types.h:704:28), (lambda at /ci_container_base/src/ipc/libmultiprocess/include/mp/proxy-types.h:705:13)>'
[02:41:41.544] 704 | return ReplaceVoid([&]() { return fn.invoke(server_context, ArgList()); },
[02:41:41.544] | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] 705 | [&]() { return kj::Promise<CallContext>(kj::mv(call_context)); })
[02:41:41.544] | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] /ci_container_base/src/ipc/libmultiprocess/include/mp/proxy-types.h:665:19: note: 'is_same_v' is true
[02:41:41.544] 665 | if constexpr (std::is_same_v<decltype(fn()), void>) {
[02:41:41.544] | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] /ci_container_base/src/ipc/libmultiprocess/include/mp/proxy-types.h:665:5: note: Taking true branch
[02:41:41.544] 665 | if constexpr (std::is_same_v<decltype(fn()), void>) {
[02:41:41.544] | ^
[02:41:41.544] /ci_container_base/src/ipc/libmultiprocess/include/mp/proxy-types.h:666:9: note: Calling 'operator()'
[02:41:41.544] 666 | fn();
[02:41:41.544] | ^~~~
[02:41:41.544] /ci_container_base/src/ipc/libmultiprocess/include/mp/proxy-types.h:704:43: note: Calling 'ServerField::invoke'
[02:41:41.544] 704 | return ReplaceVoid([&]() { return fn.invoke(server_context, ArgList()); },
[02:41:41.544] | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] /ci_container_base/src/ipc/libmultiprocess/include/mp/proxy-types.h:539:16: note: Calling 'PassField<mp::Accessor<mp::foo_fields::Arg, 17>, mp::test::FooCustom, mp::ServerInvokeContext<mp::ProxyServer<mp::test::messages::FooInterface>, capnp::CallContext<mp::test::messages::FooInterface::PassCustomParams, mp::test::messages::FooInterface::PassCustomResults>>, const mp::ServerRet<mp::Accessor<mp::foo_fields::Result, 18>, mp::ServerCall> &, mp::TypeList<>>'
[02:41:41.544] 539 | return PassField<Accessor>(Priority<2>(),
[02:41:41.544] | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] 540 | typename Split<argc, ArgTypes>::First(),
[02:41:41.544] | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] 541 | server_context,
[02:41:41.544] | ~~~~~~~~~~~~~~~
[02:41:41.544] 542 | this->parent(),
[02:41:41.544] | ~~~~~~~~~~~~~~~
[02:41:41.544] 543 | typename Split<argc, ArgTypes>::Second(),
[02:41:41.544] | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] 544 | std::forward<Args>(args)...);
[02:41:41.544] | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] /ci_container_base/src/ipc/libmultiprocess/include/mp/proxy-types.h:297:5: note: Calling 'MaybeReadField<mp::TypeList<mp::test::FooCustom>, mp::InvokeContext &, mp::StructField<mp::Accessor<mp::foo_fields::Arg, 17>, const mp::test::messages::FooInterface::PassCustomParams::Reader>, mp::ReadDestEmplace<mp::test::FooCustom, (lambda at /ci_container_base/src/ipc/libmultiprocess/include/mp/proxy-types.h:298:83)>>'
[02:41:41.544] 297 | MaybeReadField(std::integral_constant<bool, Accessor::in>(), TypeList<ArgType>(), invoke_context,
[02:41:41.544] | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] 298 | Make<StructField, Accessor>(params), ReadDestEmplace(TypeList<ArgType>(), [&](auto&&... args) -> auto& {
[02:41:41.544] | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] 299 | param.emplace(std::forward<decltype(args)>(args)...);
[02:41:41.544] | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] 300 | return *param;
[02:41:41.544] | ~~~~~~~~~~~~~~
[02:41:41.544] 301 | }));
[02:41:41.544] | ~~~
[02:41:41.544] /ci_container_base/src/ipc/libmultiprocess/include/mp/proxy-types.h:269:5: note: Calling 'ReadField<mp::test::FooCustom, mp::InvokeContext &, mp::StructField<mp::Accessor<mp::foo_fields::Arg, 17>, const mp::test::messages::FooInterface::PassCustomParams::Reader>, mp::ReadDestEmplace<mp::test::FooCustom, (lambda at /ci_container_base/src/ipc/libmultiprocess/include/mp/proxy-types.h:298:83)>>'
[02:41:41.544] 269 | ReadField(std::forward<Args>(args)...);
[02:41:41.544] | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] /ci_container_base/src/ipc/libmultiprocess/include/mp/proxy-types.h:172:12: note: Calling 'CustomReadField<mp::StructField<mp::Accessor<mp::foo_fields::Arg, 17>, const mp::test::messages::FooInterface::PassCustomParams::Reader>, mp::ReadDestEmplace<mp::test::FooCustom, (lambda at /ci_container_base/src/ipc/libmultiprocess/include/mp/proxy-types.h:298:83)>>'
[02:41:41.544] 172 | return CustomReadField(TypeList<RemoveCvRef<LocalTypes>...>(), Priority<2>(), std::forward<Args>(args)...);
[02:41:41.544] | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] /ci_container_base/src/ipc/libmultiprocess/test/mp/test/foo-types.h:35:12: note: Calling 'ReadDestEmplace::update'
[02:41:41.544] 35 | return read_dest.update([&](FooCustom& value) {
[02:41:41.544] | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] 36 | value.v1 = ReadField(TypeList<std::string>(), invoke_context, mp::Make<mp::ValueField>(custom.getV1()), ReadDestTemp<std::string>());
[02:41:41.544] | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] 37 | value.v2 = custom.getV2();
[02:41:41.544] | ~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] 38 | });
[02:41:41.544] | ~~
[02:41:41.544] /ci_container_base/src/ipc/libmultiprocess/include/mp/proxy-types.h:112:23: note: 'is_const_v' is false
[02:41:41.544] 112 | if constexpr (std::is_const_v<std::remove_reference_t<std::invoke_result_t<EmplaceFn>>>) {
[02:41:41.544] | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] /ci_container_base/src/ipc/libmultiprocess/include/mp/proxy-types.h:112:9: note: Taking false branch
[02:41:41.544] 112 | if constexpr (std::is_const_v<std::remove_reference_t<std::invoke_result_t<EmplaceFn>>>) {
[02:41:41.544] | ^
[02:41:41.544] /ci_container_base/src/ipc/libmultiprocess/include/mp/proxy-types.h:122:13: note: Calling 'operator()'
[02:41:41.544] 122 | update_fn(temp);
[02:41:41.544] | ^~~~~~~~~~~~~~~
[02:41:41.544] /ci_container_base/src/ipc/libmultiprocess/test/mp/test/foo-types.h:36:113: note: Calling 'ReadDestTemp<std::basic_string<char>>'
[02:41:41.544] 36 | value.v1 = ReadField(TypeList<std::string>(), invoke_context, mp::Make<mp::ValueField>(custom.getV1()), ReadDestTemp<std::string>());
[02:41:41.544] | ^~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] /ci_container_base/src/ipc/libmultiprocess/include/mp/proxy-types.h:134:5: note: Address of stack memory associated with temporary object of type '(lambda at /ci_container_base/src/ipc/libmultiprocess/include/mp/proxy-types.h:134:51)' is still referred to by a temporary object on the stack upon returning to the caller. This will be a dangling reference
[02:41:41.544] 134 | return ReadDestEmplace{TypeList<LocalType>(), [&](auto&&... args) -> decltype(auto) {
[02:41:41.544] | ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] 135 | return LocalType{std::forward<decltype(args)>(args)...};
[02:41:41.544] | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] 136 | }};
[02:41:41.544] | ~
[02:41:41.544] /ci_container_base/src/ipc/libmultiprocess/include/mp/type-number.h:55:32: warning: The value '0' provided to the cast expression is not in the valid range of values for 'FooEnum' [clang-analyzer-optin.core.EnumCastOutOfRange]
[02:41:41.544] 55 | return read_dest.construct(static_cast<LocalType>(input.get()));
[02:41:41.544] | ^
[02:41:41.544] /ci_container_base/src/ipc/libmultiprocess/test/mp/test/foo.h:24:12: note: enum declared here
[02:41:41.544] 24 | enum class FooEnum : uint8_t { ONE = 1, TWO = 2, };
[02:41:41.544] | ~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] /ci_container_base/ci/scratch/build-x86_64-pc-linux-gnu/src/ipc/libmultiprocess/test/mp/test/foo.capnp.proxy-server.c++:53:12: note: Calling 'serverInvoke<mp::ProxyServer<mp::test::messages::FooInterface>, capnp::CallContext<mp::test::messages::FooInterface::PassEnumParams, mp::test::messages::FooInterface::PassEnumResults>, mp::ServerField<1, mp::Accessor<mp::foo_fields::Arg, 1>, mp::ServerRet<mp::Accessor<mp::foo_fields::Result, 2>, mp::ServerCall>>>'
[02:41:41.544] 53 | return serverInvoke(*this, call_context, MakeServerField<1, Accessor<foo_fields::Arg, FIELD_IN>>(Make<ServerRet, Accessor<foo_fields::Result, FIELD_OUT>>(ServerCall())));
[02:41:41.544] | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] /ci_container_base/src/ipc/libmultiprocess/include/mp/proxy-types.h:704:16: note: Calling 'ReplaceVoid<(lambda at /ci_container_base/src/ipc/libmultiprocess/include/mp/proxy-types.h:704:28), (lambda at /ci_container_base/src/ipc/libmultiprocess/include/mp/proxy-types.h:705:13)>'
[02:41:41.544] 704 | return ReplaceVoid([&]() { return fn.invoke(server_context, ArgList()); },
[02:41:41.544] | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] 705 | [&]() { return kj::Promise<CallContext>(kj::mv(call_context)); })
[02:41:41.544] | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] /ci_container_base/src/ipc/libmultiprocess/include/mp/proxy-types.h:665:19: note: 'is_same_v' is true
[02:41:41.544] 665 | if constexpr (std::is_same_v<decltype(fn()), void>) {
[02:41:41.544] | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] /ci_container_base/src/ipc/libmultiprocess/include/mp/proxy-types.h:665:5: note: Taking true branch
[02:41:41.544] 665 | if constexpr (std::is_same_v<decltype(fn()), void>) {
[02:41:41.544] | ^
[02:41:41.544] /ci_container_base/src/ipc/libmultiprocess/include/mp/proxy-types.h:666:9: note: Calling 'operator()'
[02:41:41.544] 666 | fn();
[02:41:41.544] | ^~~~
[02:41:41.544] /ci_container_base/src/ipc/libmultiprocess/include/mp/proxy-types.h:704:43: note: Calling 'ServerField::invoke'
[02:41:41.544] 704 | return ReplaceVoid([&]() { return fn.invoke(server_context, ArgList()); },
[02:41:41.544] | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] /ci_container_base/src/ipc/libmultiprocess/include/mp/proxy-types.h:539:16: note: Calling 'PassField<mp::Accessor<mp::foo_fields::Arg, 1>, mp::test::FooEnum, mp::ServerInvokeContext<mp::ProxyServer<mp::test::messages::FooInterface>, capnp::CallContext<mp::test::messages::FooInterface::PassEnumParams, mp::test::messages::FooInterface::PassEnumResults>>, const mp::ServerRet<mp::Accessor<mp::foo_fields::Result, 2>, mp::ServerCall> &, mp::TypeList<>>'
[02:41:41.544] 539 | return PassField<Accessor>(Priority<2>(),
[02:41:41.544] | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] 540 | typename Split<argc, ArgTypes>::First(),
[02:41:41.544] | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] 541 | server_context,
[02:41:41.544] | ~~~~~~~~~~~~~~~
[02:41:41.544] 542 | this->parent(),
[02:41:41.544] | ~~~~~~~~~~~~~~~
[02:41:41.544] 543 | typename Split<argc, ArgTypes>::Second(),
[02:41:41.544] | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] 544 | std::forward<Args>(args)...);
[02:41:41.544] | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] /ci_container_base/src/ipc/libmultiprocess/include/mp/proxy-types.h:297:5: note: Calling 'MaybeReadField<mp::TypeList<mp::test::FooEnum>, mp::InvokeContext &, mp::StructField<mp::Accessor<mp::foo_fields::Arg, 1>, const mp::test::messages::FooInterface::PassEnumParams::Reader>, mp::ReadDestEmplace<mp::test::FooEnum, (lambda at /ci_container_base/src/ipc/libmultiprocess/include/mp/proxy-types.h:298:83)>>'
[02:41:41.544] 297 | MaybeReadField(std::integral_constant<bool, Accessor::in>(), TypeList<ArgType>(), invoke_context,
[02:41:41.544] | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] 298 | Make<StructField, Accessor>(params), ReadDestEmplace(TypeList<ArgType>(), [&](auto&&... args) -> auto& {
[02:41:41.544] | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] 299 | param.emplace(std::forward<decltype(args)>(args)...);
[02:41:41.544] | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] 300 | return *param;
[02:41:41.544] | ~~~~~~~~~~~~~~
[02:41:41.544] 301 | }));
[02:41:41.544] | ~~~
[02:41:41.544] /ci_container_base/src/ipc/libmultiprocess/include/mp/proxy-types.h:269:5: note: Calling 'ReadField<mp::test::FooEnum, mp::InvokeContext &, mp::StructField<mp::Accessor<mp::foo_fields::Arg, 1>, const mp::test::messages::FooInterface::PassEnumParams::Reader>, mp::ReadDestEmplace<mp::test::FooEnum, (lambda at /ci_container_base/src/ipc/libmultiprocess/include/mp/proxy-types.h:298:83)>>'
[02:41:41.544] 269 | ReadField(std::forward<Args>(args)...);
[02:41:41.544] | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] /ci_container_base/src/ipc/libmultiprocess/include/mp/proxy-types.h:172:12: note: Calling 'CustomReadField<mp::test::FooEnum, mp::StructField<mp::Accessor<mp::foo_fields::Arg, 1>, const mp::test::messages::FooInterface::PassEnumParams::Reader>, mp::ReadDestEmplace<mp::test::FooEnum, (lambda at /ci_container_base/src/ipc/libmultiprocess/include/mp/proxy-types.h:298:83)>>'
[02:41:41.544] 172 | return CustomReadField(TypeList<RemoveCvRef<LocalTypes>...>(), Priority<2>(), std::forward<Args>(args)...);
[02:41:41.544] | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] /ci_container_base/src/ipc/libmultiprocess/include/mp/type-number.h:55:55: note: Calling 'StructField::get'
[02:41:41.544] 55 | return read_dest.construct(static_cast<LocalType>(input.get()));
[02:41:41.544] | ^~~~~~~~~~~
[02:41:41.544] /ci_container_base/src/ipc/libmultiprocess/include/mp/proxy-types.h:40:41: note: Calling 'Arg::get'
[02:41:41.544] 40 | decltype(auto) get() const { return Accessor::get(this->m_struct); }
[02:41:41.544] | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] /ci_container_base/ci/scratch/build-x86_64-pc-linux-gnu/src/ipc/libmultiprocess/test/mp/test/foo.capnp.proxy.h:174:82: note: Calling 'Reader::getArg'
[02:41:41.544] 174 | template<typename S> static auto get(S&& s) -> decltype(s.getArg()) { return s.getArg(); }
[02:41:41.544] | ^~~~~~~~~~
[02:41:41.544] /ci_container_base/ci/scratch/build-x86_64-pc-linux-gnu/src/ipc/libmultiprocess/test/mp/test/foo.capnp.h:5998:10: note: Calling 'StructReader::getDataField'
[02:41:41.544] 5998 | return _reader.getDataField< ::int32_t>(
[02:41:41.544] | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] 5999 | ::capnp::bounded<0>() * ::capnp::ELEMENTS);
[02:41:41.544] | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] /usr/include/capnp/layout.h:1099:7: note: Assuming the condition is false
[02:41:41.544] 1099 | if ((offset + ONE * ELEMENTS) * capnp::bitsPerElement<T>() <= dataSize) {
[02:41:41.544] | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] /usr/include/capnp/layout.h:1099:3: note: Taking false branch
[02:41:41.544] 1099 | if ((offset + ONE * ELEMENTS) * capnp::bitsPerElement<T>() <= dataSize) {
[02:41:41.544] | ^
[02:41:41.544] /usr/include/capnp/layout.h:1102:5: note: Returning zero
[02:41:41.544] 1102 | return static_cast<T>(0);
[02:41:41.544] | ^~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] /ci_container_base/ci/scratch/build-x86_64-pc-linux-gnu/src/ipc/libmultiprocess/test/mp/test/foo.capnp.h:5998:10: note: Returning from 'StructReader::getDataField'
[02:41:41.544] 5998 | return _reader.getDataField< ::int32_t>(
[02:41:41.544] | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] 5999 | ::capnp::bounded<0>() * ::capnp::ELEMENTS);
[02:41:41.544] | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] /ci_container_base/ci/scratch/build-x86_64-pc-linux-gnu/src/ipc/libmultiprocess/test/mp/test/foo.capnp.h:5998:3: note: Returning zero
[02:41:41.544] 5998 | return _reader.getDataField< ::int32_t>(
[02:41:41.544] | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] 5999 | ::capnp::bounded<0>() * ::capnp::ELEMENTS);
[02:41:41.544] | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] /ci_container_base/ci/scratch/build-x86_64-pc-linux-gnu/src/ipc/libmultiprocess/test/mp/test/foo.capnp.proxy.h:174:82: note: Returning from 'Reader::getArg'
[02:41:41.544] 174 | template<typename S> static auto get(S&& s) -> decltype(s.getArg()) { return s.getArg(); }
[02:41:41.544] | ^~~~~~~~~~
[02:41:41.544] /ci_container_base/ci/scratch/build-x86_64-pc-linux-gnu/src/ipc/libmultiprocess/test/mp/test/foo.capnp.proxy.h:174:75: note: Returning zero
[02:41:41.544] 174 | template<typename S> static auto get(S&& s) -> decltype(s.getArg()) { return s.getArg(); }
[02:41:41.544] | ^~~~~~~~~~~~~~~~~
[02:41:41.544] /ci_container_base/src/ipc/libmultiprocess/include/mp/proxy-types.h:40:41: note: Returning from 'Arg::get'
[02:41:41.544] 40 | decltype(auto) get() const { return Accessor::get(this->m_struct); }
[02:41:41.544] | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] /ci_container_base/src/ipc/libmultiprocess/include/mp/proxy-types.h:40:34: note: Returning zero
[02:41:41.544] 40 | decltype(auto) get() const { return Accessor::get(this->m_struct); }
[02:41:41.544] | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] /ci_container_base/src/ipc/libmultiprocess/include/mp/type-number.h:55:55: note: Returning from 'StructField::get'
[02:41:41.544] 55 | return read_dest.construct(static_cast<LocalType>(input.get()));
[02:41:41.544] | ^~~~~~~~~~~
[02:41:41.544] /ci_container_base/src/ipc/libmultiprocess/include/mp/type-number.h:55:32: note: The value '0' provided to the cast expression is not in the valid range of values for 'FooEnum'
[02:41:41.544] 55 | return read_dest.construct(static_cast<LocalType>(input.get()));
[02:41:41.544] | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] /usr/include/kj/async-inl.h:609:37: warning: The left operand of '+' is a garbage value [clang-analyzer-core.UndefinedBinaryOperatorResult]
[02:41:41.544] 609 | return *(void**)(*(char**)obj + voff);
[02:41:41.544] | ^
[02:41:41.544] /ci_container_base/ci/scratch/build-x86_64-pc-linux-gnu/src/ipc/libmultiprocess/test/mp/test/foo.capnp.proxy-server.c++:68:12: note: Calling 'serverInvoke<mp::ProxyServer<mp::test::messages::ExtendedCallback>, capnp::CallContext<mp::test::messages::ExtendedCallback::CallExtendedParams, mp::test::messages::ExtendedCallback::CallExtendedResults>, mp::ServerField<0, mp::Accessor<mp::foo_fields::Context, 17>, mp::ServerField<1, mp::Accessor<mp::foo_fields::Arg, 1>, mp::ServerRet<mp::Accessor<mp::foo_fields::Result, 2>, mp::ServerCall>>>>'
[02:41:41.544] 68 | return serverInvoke(*this, call_context, MakeServerField<0, Accessor<foo_fields::Context, FIELD_IN | FIELD_BOXED>>(MakeServerField<1, Accessor<foo_fields::Arg, FIELD_IN>>(Make<ServerRet, Accessor<foo_fields::Result, FIELD_OUT>>(ServerCall()))));
[02:41:41.544] | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] /ci_container_base/src/ipc/libmultiprocess/include/mp/proxy-types.h:704:16: note: Calling 'ReplaceVoid<(lambda at /ci_container_base/src/ipc/libmultiprocess/include/mp/proxy-types.h:704:28), (lambda at /ci_container_base/src/ipc/libmultiprocess/include/mp/proxy-types.h:705:13)>'
[02:41:41.544] 704 | return ReplaceVoid([&]() { return fn.invoke(server_context, ArgList()); },
[02:41:41.544] | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] 705 | [&]() { return kj::Promise<CallContext>(kj::mv(call_context)); })
[02:41:41.544] | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] /ci_container_base/src/ipc/libmultiprocess/include/mp/proxy-types.h:665:19: note: 'is_same_v' is false
[02:41:41.544] 665 | if constexpr (std::is_same_v<decltype(fn()), void>) {
[02:41:41.544] | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] /ci_container_base/src/ipc/libmultiprocess/include/mp/proxy-types.h:665:5: note: Taking false branch
[02:41:41.544] 665 | if constexpr (std::is_same_v<decltype(fn()), void>) {
[02:41:41.544] | ^
[02:41:41.544] /ci_container_base/src/ipc/libmultiprocess/include/mp/proxy-types.h:669:16: note: Calling 'operator()'
[02:41:41.544] 669 | return fn();
[02:41:41.544] | ^~~~
[02:41:41.544] /ci_container_base/src/ipc/libmultiprocess/include/mp/proxy-types.h:704:43: note: Calling 'ServerField::invoke'
[02:41:41.544] 704 | return ReplaceVoid([&]() { return fn.invoke(server_context, ArgList()); },
[02:41:41.544] | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] /ci_container_base/src/ipc/libmultiprocess/include/mp/proxy-types.h:539:16: note: Calling 'PassField<mp::Accessor<mp::foo_fields::Context, 17>, mp::ServerInvokeContext<mp::ProxyServer<mp::test::messages::ExtendedCallback>, capnp::CallContext<mp::test::messages::ExtendedCallback::CallExtendedParams, mp::test::messages::ExtendedCallback::CallExtendedResults>>, mp::ServerField<1, mp::Accessor<mp::foo_fields::Arg, 1>, mp::ServerRet<mp::Accessor<mp::foo_fields::Result, 2>, mp::ServerCall>>, mp::TypeList<int>>'
[02:41:41.544] 539 | return PassField<Accessor>(Priority<2>(),
[02:41:41.544] | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] 540 | typename Split<argc, ArgTypes>::First(),
[02:41:41.544] | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] 541 | server_context,
[02:41:41.544] | ~~~~~~~~~~~~~~~
[02:41:41.544] 542 | this->parent(),
[02:41:41.544] | ~~~~~~~~~~~~~~~
[02:41:41.544] 543 | typename Split<argc, ArgTypes>::Second(),
[02:41:41.544] | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] 544 | std::forward<Args>(args)...);
[02:41:41.544] | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] /ci_container_base/src/ipc/libmultiprocess/include/mp/type-context.h:152:12: note: Calling 'CapabilityServerSet::getLocalServer'
[02:41:41.544] 152 | return server.m_context.connection->m_threads.getLocalServer(thread_client)
[02:41:41.544] | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] /usr/include/capnp/capability.h:1274:10: note: Calling 'Promise::then'
[02:41:41.544] 1274 | return getLocalServerInternal(client)
[02:41:41.544] | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] 1275 | .then([](void* server) -> kj::Maybe<typename T::Server&> {
[02:41:41.544] | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] 1276 | if (server == nullptr) {
[02:41:41.544] | ~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] 1277 | return nullptr;
[02:41:41.544] | ~~~~~~~~~~~~~~~
[02:41:41.544] 1278 | } else {
[02:41:41.544] | ~~~~~~~~
[02:41:41.544] 1279 | return *reinterpret_cast<typename T::Server*>(server);
[02:41:41.544] | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] 1280 | }
[02:41:41.544] | ~
[02:41:41.544] 1281 | });
[02:41:41.544] | ~~
[02:41:41.544] /usr/include/kj/async-inl.h:1295:32: note: Calling 'GetFunctorStartAddress::apply'
[02:41:41.544] 1295 | void* continuationTracePtr = _::GetFunctorStartAddress<_::FixVoid<T>&&>::apply(func);
[02:41:41.544] | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] /usr/include/kj/async-inl.h:677:12: note: Calling 'PtmfHelper::apply'
[02:41:41.544] 677 | return PtmfHelper::from<ReturnType, Decay<Func>, ParamTypes...>(
[02:41:41.544] | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] 678 | &Decay<Func>::operator()).apply(&func);
[02:41:41.544] | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02:41:41.544] /usr/include/kj/async-inl.h:606:9: note: Assuming the condition is true
[02:41:41.544] 606 | if (voff & 1) {
[02:41:41.544] | ^~~~~~~~
[02:41:41.544] /usr/include/kj/async-inl.h:606:5: note: Taking true branch
[02:41:41.544] 606 | if (voff & 1) {
[02:41:41.544] | ^
[02:41:41.544] /usr/include/kj/async-inl.h:609:37: note: The left operand of '+' is a garbage value
[02:41:41.544] 609 | return *(void**)(*(char**)obj + voff);
[02:41:41.544] | ~~~~~~~~~~~~ ^
[02:41:41.545] 3 warnings generated. |
re: #31802 (comment)
Thanks, will fix. Looks like bitcoin-core/libmultiprocess#172 did not resolve all the warnings. Just taking a quick look:
Update: These are all addressed in bitcoin-core/libmultiprocess#184 |
This error should not be a real problem because code is taking an invalid reference to an empty object that has no state and could never be used. But taking the reference could technically be undefined behavior. Reported by fanquake <[email protected]> bitcoin/bitcoin#31802 (comment) https://cirrus-ci.com/task/6552721135763456 https://api.cirrus-ci.com/v1/task/6552721135763456/logs/ci.log include/mp/proxy-types.h:134:5: error: Address of stack memory associated with temporary object of type '(lambda at include/mp/proxy-types.h:134:51)' is still referred to by a temporary object on the stack upon returning to the caller. This will be a dangling reference [clang-analyzer-core.StackAddressEscape,-warnings-as-errors] 134 | return ReadDestEmplace{TypeList<LocalType>(), [&](auto&&... args) -> decltype(auto) { | ^ build/test/mp/test/foo.capnp.proxy-server.c++:51:12: note: Calling 'serverInvoke<mp::ProxyServer<mp::test::messages::FooInterface>, capnp::CallContext<mp::test::messages::FooInterface::PassCustomParams, mp::test::messages::FooInterface::PassCustomResults>, mp::ServerField<1, mp::Accessor<mp::foo_fields::Arg, 17>, mp::ServerRet<mp::Accessor<mp::foo_fields::Result, 18>, mp::ServerCall>>>' 51 | return serverInvoke(*this, call_context, MakeServerField<1, Accessor<foo_fields::Arg, FIELD_IN | FIELD_BOXED>>(Make<ServerRet, Accessor<foo_fields::Result, FIELD_OUT | FIELD_BOXED>>(ServerCall()))); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/mp/proxy-types.h:739:16: note: Calling 'ReplaceVoid<(lambda at include/mp/proxy-types.h:739:28), (lambda at include/mp/proxy-types.h:740:13)>' 739 | return ReplaceVoid([&]() { return fn.invoke(server_context, ArgList()); }, | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 740 | [&]() { return kj::Promise<CallContext>(kj::mv(call_context)); }) | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/mp/proxy-types.h:700:19: note: 'is_same_v' is true 700 | if constexpr (std::is_same_v<decltype(fn()), void>) { | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/mp/proxy-types.h:700:5: note: Taking true branch 700 | if constexpr (std::is_same_v<decltype(fn()), void>) { | ^ include/mp/proxy-types.h:701:9: note: Calling 'operator()' 701 | fn(); | ^~~~ include/mp/proxy-types.h:739:43: note: Calling 'ServerField::invoke' 739 | return ReplaceVoid([&]() { return fn.invoke(server_context, ArgList()); }, | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/mp/proxy-types.h:563:16: note: Calling 'PassField<mp::Accessor<mp::foo_fields::Arg, 17>, mp::test::FooCustom, mp::ServerInvokeContext<mp::ProxyServer<mp::test::messages::FooInterface>, capnp::CallContext<mp::test::messages::FooInterface::PassCustomParams, mp::test::messages::FooInterface::PassCustomResults>>, const mp::ServerRet<mp::Accessor<mp::foo_fields::Result, 18>, mp::ServerCall> &, mp::TypeList<>>' 563 | return PassField<Accessor>(Priority<2>(), | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 564 | typename Split<argc, ArgTypes>::First(), | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 565 | server_context, | ~~~~~~~~~~~~~~~ 566 | this->parent(), | ~~~~~~~~~~~~~~~ 567 | typename Split<argc, ArgTypes>::Second(), | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 568 | std::forward<Args>(args)...); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/mp/proxy-types.h:304:5: note: Calling 'MaybeReadField<mp::TypeList<mp::test::FooCustom>, mp::InvokeContext &, mp::StructField<mp::Accessor<mp::foo_fields::Arg, 17>, const mp::test::messages::FooInterface::PassCustomParams::Reader>, mp::ReadDestEmplace<mp::test::FooCustom, (lambda at include/mp/proxy-types.h:305:83)>>' 304 | MaybeReadField(std::integral_constant<bool, Accessor::in>(), TypeList<ArgType>(), invoke_context, | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 305 | Make<StructField, Accessor>(params), ReadDestEmplace(TypeList<ArgType>(), [&](auto&&... args) -> auto& { | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 306 | param.emplace(std::forward<decltype(args)>(args)...); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 307 | return *param; | ~~~~~~~~~~~~~~ 308 | })); | ~~~ include/mp/proxy-types.h:276:5: note: Calling 'ReadField<mp::test::FooCustom, mp::InvokeContext &, mp::StructField<mp::Accessor<mp::foo_fields::Arg, 17>, const mp::test::messages::FooInterface::PassCustomParams::Reader>, mp::ReadDestEmplace<mp::test::FooCustom, (lambda at include/mp/proxy-types.h:305:83)>>' 276 | ReadField(std::forward<Args>(args)...); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/mp/proxy-types.h:175:12: note: Calling 'CustomReadField<mp::StructField<mp::Accessor<mp::foo_fields::Arg, 17>, const mp::test::messages::FooInterface::PassCustomParams::Reader>, mp::ReadDestEmplace<mp::test::FooCustom, (lambda at include/mp/proxy-types.h:305:83)>>' 175 | return CustomReadField(TypeList<RemoveCvRef<LocalTypes>...>(), Priority<2>(), std::forward<Args>(args)...); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ test/mp/test/foo-types.h:51:12: note: Calling 'ReadDestEmplace::update' 51 | return read_dest.update([&](FooCustom& value) { | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 52 | value.v1 = ReadField(TypeList<std::string>(), invoke_context, mp::Make<mp::ValueField>(custom.getV1()), ReadDestTemp<std::string>()); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 53 | value.v2 = custom.getV2(); | ~~~~~~~~~~~~~~~~~~~~~~~~~~ 54 | }); | ~~ include/mp/proxy-types.h:112:23: note: 'is_const_v' is false 112 | if constexpr (std::is_const_v<std::remove_reference_t<std::invoke_result_t<EmplaceFn>>>) { | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/mp/proxy-types.h:112:9: note: Taking false branch 112 | if constexpr (std::is_const_v<std::remove_reference_t<std::invoke_result_t<EmplaceFn>>>) { | ^ include/mp/proxy-types.h:122:13: note: Calling 'operator()' 122 | update_fn(temp); | ^~~~~~~~~~~~~~~ test/mp/test/foo-types.h:52:113: note: Calling 'ReadDestTemp<std::basic_string<char>>' 52 | value.v1 = ReadField(TypeList<std::string>(), invoke_context, mp::Make<mp::ValueField>(custom.getV1()), ReadDestTemp<std::string>()); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~ include/mp/proxy-types.h:134:5: note: Address of stack memory associated with temporary object of type '(lambda at include/mp/proxy-types.h:134:51)' is still referred to by a temporary object on the stack upon returning to the caller. This will be a dangling reference 134 | return ReadDestEmplace{TypeList<LocalType>(), [&](auto&&... args) -> decltype(auto) { | ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 135 | return LocalType{std::forward<decltype(args)>(args)...}; | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 136 | }}; | ~
Reported by fanquake <[email protected]> bitcoin/bitcoin#31802 (comment) https://cirrus-ci.com/task/6552721135763456 https://api.cirrus-ci.com/v1/task/6552721135763456/logs/ci.log include/mp/type-number.h:55:32: error: The value '0' provided to the cast expression is not in the valid range of values for 'FooEnum' [clang-analyzer-optin.core.EnumCastOutOfRange,-warnings-as-errors] 55 | return read_dest.construct(static_cast<LocalType>(input.get())); | ^ test/mp/test/foo.h:26:12: note: enum declared here 26 | enum class FooEnum : uint8_t { ONE = 1, TWO = 2, }; | ~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ build/test/mp/test/foo.capnp.proxy-server.c++:63:12: note: Calling 'serverInvoke<mp::ProxyServer<mp::test::messages::FooInterface>, capnp::CallContext<mp::test::messages::FooInterface::PassEnumParams, mp::test::messages::FooInterface::PassEnumResults>, mp::ServerField<1, mp::Accessor<mp::foo_fields::Arg, 1>, mp::ServerRet<mp::Accessor<mp::foo_fields::Result, 2>, mp::ServerCall>>>' 63 | return serverInvoke(*this, call_context, MakeServerField<1, Accessor<foo_fields::Arg, FIELD_IN>>(Make<ServerRet, Accessor<foo_fields::Result, FIELD_OUT>>(ServerCall()))); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/mp/proxy-types.h:739:16: note: Calling 'ReplaceVoid<(lambda at include/mp/proxy-types.h:739:28), (lambda at include/mp/proxy-types.h:740:13)>' 739 | return ReplaceVoid([&]() { return fn.invoke(server_context, ArgList()); }, | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 740 | [&]() { return kj::Promise<CallContext>(kj::mv(call_context)); }) | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/mp/proxy-types.h:700:19: note: 'is_same_v' is true 700 | if constexpr (std::is_same_v<decltype(fn()), void>) { | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/mp/proxy-types.h:700:5: note: Taking true branch 700 | if constexpr (std::is_same_v<decltype(fn()), void>) { | ^ include/mp/proxy-types.h:701:9: note: Calling 'operator()' 701 | fn(); | ^~~~ include/mp/proxy-types.h:739:43: note: Calling 'ServerField::invoke' 739 | return ReplaceVoid([&]() { return fn.invoke(server_context, ArgList()); }, | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/mp/proxy-types.h:563:16: note: Calling 'PassField<mp::Accessor<mp::foo_fields::Arg, 1>, mp::test::FooEnum, mp::ServerInvokeContext<mp::ProxyServer<mp::test::messages::FooInterface>, capnp::CallContext<mp::test::messages::FooInterface::PassEnumParams, mp::test::messages::FooInterface::PassEnumResults>>, const mp::ServerRet<mp::Accessor<mp::foo_fields::Result, 2>, mp::ServerCall> &, mp::TypeList<>>' 563 | return PassField<Accessor>(Priority<2>(), | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 564 | typename Split<argc, ArgTypes>::First(), | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 565 | server_context, | ~~~~~~~~~~~~~~~ 566 | this->parent(), | ~~~~~~~~~~~~~~~ 567 | typename Split<argc, ArgTypes>::Second(), | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 568 | std::forward<Args>(args)...); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/mp/proxy-types.h:304:5: note: Calling 'MaybeReadField<mp::TypeList<mp::test::FooEnum>, mp::InvokeContext &, mp::StructField<mp::Accessor<mp::foo_fields::Arg, 1>, const mp::test::messages::FooInterface::PassEnumParams::Reader>, mp::ReadDestEmplace<mp::test::FooEnum, (lambda at include/mp/proxy-types.h:305:83)>>' 304 | MaybeReadField(std::integral_constant<bool, Accessor::in>(), TypeList<ArgType>(), invoke_context, | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 305 | Make<StructField, Accessor>(params), ReadDestEmplace(TypeList<ArgType>(), [&](auto&&... args) -> auto& { | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 306 | param.emplace(std::forward<decltype(args)>(args)...); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 307 | return *param; | ~~~~~~~~~~~~~~ 308 | })); | ~~~ include/mp/proxy-types.h:276:5: note: Calling 'ReadField<mp::test::FooEnum, mp::InvokeContext &, mp::StructField<mp::Accessor<mp::foo_fields::Arg, 1>, const mp::test::messages::FooInterface::PassEnumParams::Reader>, mp::ReadDestEmplace<mp::test::FooEnum, (lambda at include/mp/proxy-types.h:305:83)>>' 276 | ReadField(std::forward<Args>(args)...); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/mp/proxy-types.h:175:12: note: Calling 'CustomReadField<mp::test::FooEnum, mp::StructField<mp::Accessor<mp::foo_fields::Arg, 1>, const mp::test::messages::FooInterface::PassEnumParams::Reader>, mp::ReadDestEmplace<mp::test::FooEnum, (lambda at include/mp/proxy-types.h:305:83)>>' 175 | return CustomReadField(TypeList<RemoveCvRef<LocalTypes>...>(), Priority<2>(), std::forward<Args>(args)...); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/mp/type-number.h:55:55: note: Calling 'StructField::get' 55 | return read_dest.construct(static_cast<LocalType>(input.get())); | ^~~~~~~~~~~ include/mp/proxy-types.h:40:41: note: Calling 'Arg::get' 40 | decltype(auto) get() const { return Accessor::get(this->m_struct); } | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~ build/test/mp/test/foo.capnp.proxy.h:198:82: note: Calling 'Reader::getArg' 198 | template<typename S> static auto get(S&& s) -> decltype(s.getArg()) { return s.getArg(); } | ^~~~~~~~~~ build/test/mp/test/foo.capnp.h:7042:10: note: Calling 'StructReader::getDataField' 7042 | return _reader.getDataField< ::int32_t>( | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 7043 | ::capnp::bounded<0>() * ::capnp::ELEMENTS); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /nix/store/46kiq9naswgbqfc14kc9nxcbgd0rv0m2-capnproto-1.1.0/include/capnp/layout.h:1099:7: note: Assuming the condition is false 1099 | if ((offset + ONE * ELEMENTS) * capnp::bitsPerElement<T>() <= dataSize) { | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /nix/store/46kiq9naswgbqfc14kc9nxcbgd0rv0m2-capnproto-1.1.0/include/capnp/layout.h:1099:3: note: Taking false branch 1099 | if ((offset + ONE * ELEMENTS) * capnp::bitsPerElement<T>() <= dataSize) { | ^ /nix/store/46kiq9naswgbqfc14kc9nxcbgd0rv0m2-capnproto-1.1.0/include/capnp/layout.h:1102:5: note: Returning zero 1102 | return static_cast<T>(0); | ^~~~~~~~~~~~~~~~~~~~~~~~ build/test/mp/test/foo.capnp.h:7042:10: note: Returning from 'StructReader::getDataField' 7042 | return _reader.getDataField< ::int32_t>( | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 7043 | ::capnp::bounded<0>() * ::capnp::ELEMENTS); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ build/test/mp/test/foo.capnp.h:7042:3: note: Returning zero 7042 | return _reader.getDataField< ::int32_t>( | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 7043 | ::capnp::bounded<0>() * ::capnp::ELEMENTS); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ build/test/mp/test/foo.capnp.proxy.h:198:82: note: Returning from 'Reader::getArg' 198 | template<typename S> static auto get(S&& s) -> decltype(s.getArg()) { return s.getArg(); } | ^~~~~~~~~~ build/test/mp/test/foo.capnp.proxy.h:198:75: note: Returning zero 198 | template<typename S> static auto get(S&& s) -> decltype(s.getArg()) { return s.getArg(); } | ^~~~~~~~~~~~~~~~~ include/mp/proxy-types.h:40:41: note: Returning from 'Arg::get' 40 | decltype(auto) get() const { return Accessor::get(this->m_struct); } | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/mp/proxy-types.h:40:34: note: Returning zero 40 | decltype(auto) get() const { return Accessor::get(this->m_struct); } | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/mp/type-number.h:55:55: note: Returning from 'StructField::get' 55 | return read_dest.construct(static_cast<LocalType>(input.get())); | ^~~~~~~~~~~ include/mp/type-number.h:55:32: note: The value '0' provided to the cast expression is not in the valid range of values for 'FooEnum' 55 | return read_dest.construct(static_cast<LocalType>(input.get())); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Reported by fanquake <[email protected]> bitcoin/bitcoin#31802 (comment) https://cirrus-ci.com/task/6552721135763456 https://api.cirrus-ci.com/v1/task/6552721135763456/logs/ci.log Error is spurious and comes from kj/async-inl.h and it seems to be shown because clang-tidy considers this error to come from "main file" of the translation unit (see https://clang.llvm.org/extra/clang-tidy/, https://stackoverflow.com/a/47611238, https://reviews.llvm.org/D26418) even though this is not the case. Even though the header is included via -isystem and clang-tidy --dump-config shows "SystemHeaders: false" the error is still shown. I also tried to suppress the error by editing .clang-tidy to include: HeaderFilterRegex: '.*' ExcludeHeaderFilterRegex: '.*/include/kj/async-inl\.h$' and many variations but the error is always shown, I assume because ExcludeHeaderFilterRegex does not ignore the isInMainFile condition (https://github.com/llvm/llvm-project/pull/91400/files). The actual warning is a false positive that comes from ABI-specific code in Cap'n Proto that gets the starting function address (that can be passed to addr2line) from a lambda or function object. This code calls a helper to get the starting function address from a pointer-to-member-function, which in this case is the the operator() member function. That code handles pointers to virtual member functions, so it checks if the pointer is virtual by testing its low-order bit, and if set, assumes the first bytes of the object are a vtable pointer, and does pointer arithmetic with the vtable address. Clang-tidy complains about this because it does not know the vtable address is valid, assuming incorrectly it is a "garbage value". A possible way to address this might be to submit a patch to Cap'n Proto that skips this code when __clang_analyzer__ is set. Maybe it could also be reported as an analyzer bug https://clang-analyzer.llvm.org/ https://clang.llvm.org/docs/analyzer/user-docs/FAQ.html#excluding-code-from-analysis Error output is: /nix/store/46kiq9naswgbqfc14kc9nxcbgd0rv0m2-capnproto-1.1.0/include/kj/async-inl.h:609:37: error: The left operand of '+' is a garbage value [clang-analyzer-core.UndefinedBinaryOperatorResult,-warnings-as-errors] 609 | return *(void**)(*(char**)obj + voff); | ^ build/test/mp/test/foo.capnp.proxy-server.c++:93:12: note: Calling 'serverInvoke<mp::ProxyServer<mp::test::messages::FooFn>, capnp::CallContext<mp::test::messages::FooFn::CallParams, mp::test::messages::FooFn::CallResults>, mp::ServerField<0, mp::Accessor<mp::foo_fields::Context, 17>, mp::ServerRet<mp::Accessor<mp::foo_fields::Result, 2>, mp::ServerCall>>>' 93 | return serverInvoke(*this, call_context, MakeServerField<0, Accessor<foo_fields::Context, FIELD_IN | FIELD_BOXED>>(Make<ServerRet, Accessor<foo_fields::Result, FIELD_OUT>>(ServerCall()))); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/mp/proxy-types.h:739:16: note: Calling 'ReplaceVoid<(lambda at include/mp/proxy-types.h:739:28), (lambda at include/mp/proxy-types.h:740:13)>' 739 | return ReplaceVoid([&]() { return fn.invoke(server_context, ArgList()); }, | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 740 | [&]() { return kj::Promise<CallContext>(kj::mv(call_context)); }) | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/mp/proxy-types.h:700:19: note: 'is_same_v' is false 700 | if constexpr (std::is_same_v<decltype(fn()), void>) { | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/mp/proxy-types.h:700:5: note: Taking false branch 700 | if constexpr (std::is_same_v<decltype(fn()), void>) { | ^ include/mp/proxy-types.h:704:16: note: Calling 'operator()' 704 | return fn(); | ^~~~ include/mp/proxy-types.h:739:43: note: Calling 'ServerField::invoke' 739 | return ReplaceVoid([&]() { return fn.invoke(server_context, ArgList()); }, | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/mp/proxy-types.h:563:16: note: Calling 'PassField<mp::Accessor<mp::foo_fields::Context, 17>, mp::ServerInvokeContext<mp::ProxyServer<mp::test::messages::FooFn>, capnp::CallContext<mp::test::messages::FooFn::CallParams, mp::test::messages::FooFn::CallResults>>, mp::ServerRet<mp::Accessor<mp::foo_fields::Result, 2>, mp::ServerCall>, mp::TypeList<>>' 563 | return PassField<Accessor>(Priority<2>(), | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 564 | typename Split<argc, ArgTypes>::First(), | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 565 | server_context, | ~~~~~~~~~~~~~~~ 566 | this->parent(), | ~~~~~~~~~~~~~~~ 567 | typename Split<argc, ArgTypes>::Second(), | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 568 | std::forward<Args>(args)...); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/mp/type-context.h:151:12: note: Calling 'CapabilityServerSet::getLocalServer' 151 | return server.m_context.connection->m_threads.getLocalServer(thread_client) | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /nix/store/46kiq9naswgbqfc14kc9nxcbgd0rv0m2-capnproto-1.1.0/include/capnp/capability.h:1274:10: note: Calling 'Promise::then' 1274 | return getLocalServerInternal(client) | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1275 | .then([](void* server) -> kj::Maybe<typename T::Server&> { | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1276 | if (server == nullptr) { | ~~~~~~~~~~~~~~~~~~~~~~~~ 1277 | return nullptr; | ~~~~~~~~~~~~~~~ 1278 | } else { | ~~~~~~~~ 1279 | return *reinterpret_cast<typename T::Server*>(server); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1280 | } | ~ 1281 | }); | ~~ /nix/store/46kiq9naswgbqfc14kc9nxcbgd0rv0m2-capnproto-1.1.0/include/kj/async-inl.h:1295:32: note: Calling 'GetFunctorStartAddress::apply' 1295 | void* continuationTracePtr = _::GetFunctorStartAddress<_::FixVoid<T>&&>::apply(func); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /nix/store/46kiq9naswgbqfc14kc9nxcbgd0rv0m2-capnproto-1.1.0/include/kj/async-inl.h:677:12: note: Calling 'PtmfHelper::apply' 677 | return PtmfHelper::from<ReturnType, Decay<Func>, ParamTypes...>( | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 678 | &Decay<Func>::operator()).apply(&func); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /nix/store/46kiq9naswgbqfc14kc9nxcbgd0rv0m2-capnproto-1.1.0/include/kj/async-inl.h:606:9: note: Assuming the condition is true 606 | if (voff & 1) { | ^~~~~~~~ /nix/store/46kiq9naswgbqfc14kc9nxcbgd0rv0m2-capnproto-1.1.0/include/kj/async-inl.h:606:5: note: Taking true branch 606 | if (voff & 1) { | ^ /nix/store/46kiq9naswgbqfc14kc9nxcbgd0rv0m2-capnproto-1.1.0/include/kj/async-inl.h:609:37: note: The left operand of '+' is a garbage value 609 | return *(void**)(*(char**)obj + voff); | ~~~~~~~~~~~~ ^
Reported by fanquake <[email protected]> bitcoin/bitcoin#31802 (comment) https://cirrus-ci.com/task/6552721135763456 https://api.cirrus-ci.com/v1/task/6552721135763456/logs/ci.log Error is spurious and comes from kj/async-inl.h and it seems to be shown because clang-tidy considers this error to come from "main file" of the translation unit (see https://clang.llvm.org/extra/clang-tidy/, https://stackoverflow.com/a/47611238, https://reviews.llvm.org/D26418) even though this is not the case. Even though the header is included via -isystem and clang-tidy --dump-config shows "SystemHeaders: false" the error is still shown. I also tried to suppress the error by editing .clang-tidy to include: HeaderFilterRegex: '.*' ExcludeHeaderFilterRegex: '.*/include/kj/async-inl\.h$' and many variations but the error is always shown, I assume because ExcludeHeaderFilterRegex does not ignore the isInMainFile condition (https://github.com/llvm/llvm-project/pull/91400/files). Adding NOLINT to the getLocalServer() line in types-context.h at the boundary between libmultiprocess and Cap'n Proto code also does not suppress the error. It does suppress clang-tidy "note:" lines below the NOLINT point in the call stack, making the error messages shorter, but the only way of suppressing the error completely seems to be either adding NOLINT inside the Cap'n Proto header, which requires a patch, or adding it to all top-level callers of the getLocalServer() function in .cpp files, which seems impractical and overbroad, and I didn't attempt. The actual warning is a false positive that comes from ABI-specific code in Cap'n Proto that gets the starting function address (that can be passed to addr2line) from a lambda or function object. This code calls a helper to get the starting function address from a pointer-to-member-function, which in this case is the the operator() member function. That code handles pointers to virtual member functions, so it checks if the pointer is virtual by testing its low-order bit, and if set, assumes the first bytes of the object are a vtable pointer, and does pointer arithmetic with the vtable address. Clang-tidy complains about this because it does not know the vtable address is valid, assuming incorrectly it is a "garbage value". I wrote patch adding NOLINT to Cap'n Proto in capnproto/capnproto#2334 which could be good long-term fix for this issue if clang-tidy does not provide a better way of suppressing the error. Complete error output is: /nix/store/46kiq9naswgbqfc14kc9nxcbgd0rv0m2-capnproto-1.1.0/include/kj/async-inl.h:609:37: error: The left operand of '+' is a garbage value [clang-analyzer-core.UndefinedBinaryOperatorResult,-warnings-as-errors] 609 | return *(void**)(*(char**)obj + voff); | ^ build/test/mp/test/foo.capnp.proxy-server.c++:93:12: note: Calling 'serverInvoke<mp::ProxyServer<mp::test::messages::FooFn>, capnp::CallContext<mp::test::messages::FooFn::CallParams, mp::test::messages::FooFn::CallResults>, mp::ServerField<0, mp::Accessor<mp::foo_fields::Context, 17>, mp::ServerRet<mp::Accessor<mp::foo_fields::Result, 2>, mp::ServerCall>>>' 93 | return serverInvoke(*this, call_context, MakeServerField<0, Accessor<foo_fields::Context, FIELD_IN | FIELD_BOXED>>(Make<ServerRet, Accessor<foo_fields::Result, FIELD_OUT>>(ServerCall()))); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/mp/proxy-types.h:739:16: note: Calling 'ReplaceVoid<(lambda at include/mp/proxy-types.h:739:28), (lambda at include/mp/proxy-types.h:740:13)>' 739 | return ReplaceVoid([&]() { return fn.invoke(server_context, ArgList()); }, | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 740 | [&]() { return kj::Promise<CallContext>(kj::mv(call_context)); }) | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/mp/proxy-types.h:700:19: note: 'is_same_v' is false 700 | if constexpr (std::is_same_v<decltype(fn()), void>) { | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/mp/proxy-types.h:700:5: note: Taking false branch 700 | if constexpr (std::is_same_v<decltype(fn()), void>) { | ^ include/mp/proxy-types.h:704:16: note: Calling 'operator()' 704 | return fn(); | ^~~~ include/mp/proxy-types.h:739:43: note: Calling 'ServerField::invoke' 739 | return ReplaceVoid([&]() { return fn.invoke(server_context, ArgList()); }, | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/mp/proxy-types.h:563:16: note: Calling 'PassField<mp::Accessor<mp::foo_fields::Context, 17>, mp::ServerInvokeContext<mp::ProxyServer<mp::test::messages::FooFn>, capnp::CallContext<mp::test::messages::FooFn::CallParams, mp::test::messages::FooFn::CallResults>>, mp::ServerRet<mp::Accessor<mp::foo_fields::Result, 2>, mp::ServerCall>, mp::TypeList<>>' 563 | return PassField<Accessor>(Priority<2>(), | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 564 | typename Split<argc, ArgTypes>::First(), | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 565 | server_context, | ~~~~~~~~~~~~~~~ 566 | this->parent(), | ~~~~~~~~~~~~~~~ 567 | typename Split<argc, ArgTypes>::Second(), | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 568 | std::forward<Args>(args)...); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/mp/type-context.h:151:12: note: Calling 'CapabilityServerSet::getLocalServer' 151 | return server.m_context.connection->m_threads.getLocalServer(thread_client) | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /nix/store/46kiq9naswgbqfc14kc9nxcbgd0rv0m2-capnproto-1.1.0/include/capnp/capability.h:1274:10: note: Calling 'Promise::then' 1274 | return getLocalServerInternal(client) | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1275 | .then([](void* server) -> kj::Maybe<typename T::Server&> { | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1276 | if (server == nullptr) { | ~~~~~~~~~~~~~~~~~~~~~~~~ 1277 | return nullptr; | ~~~~~~~~~~~~~~~ 1278 | } else { | ~~~~~~~~ 1279 | return *reinterpret_cast<typename T::Server*>(server); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1280 | } | ~ 1281 | }); | ~~ /nix/store/46kiq9naswgbqfc14kc9nxcbgd0rv0m2-capnproto-1.1.0/include/kj/async-inl.h:1295:32: note: Calling 'GetFunctorStartAddress::apply' 1295 | void* continuationTracePtr = _::GetFunctorStartAddress<_::FixVoid<T>&&>::apply(func); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /nix/store/46kiq9naswgbqfc14kc9nxcbgd0rv0m2-capnproto-1.1.0/include/kj/async-inl.h:677:12: note: Calling 'PtmfHelper::apply' 677 | return PtmfHelper::from<ReturnType, Decay<Func>, ParamTypes...>( | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 678 | &Decay<Func>::operator()).apply(&func); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /nix/store/46kiq9naswgbqfc14kc9nxcbgd0rv0m2-capnproto-1.1.0/include/kj/async-inl.h:606:9: note: Assuming the condition is true 606 | if (voff & 1) { | ^~~~~~~~ /nix/store/46kiq9naswgbqfc14kc9nxcbgd0rv0m2-capnproto-1.1.0/include/kj/async-inl.h:606:5: note: Taking true branch 606 | if (voff & 1) { | ^ /nix/store/46kiq9naswgbqfc14kc9nxcbgd0rv0m2-capnproto-1.1.0/include/kj/async-inl.h:609:37: note: The left operand of '+' is a garbage value 609 | return *(void**)(*(char**)obj + voff); | ~~~~~~~~~~~~ ^
Have depends make libmultiprocess by default. This PR causes the following behavior changes:
ENABLE_IPC
option being switched on by default in depends buildsENABLE_IPC
is also switched on by default in non-depends buildsENABLE_IPC
on in most configurations and usingbitcoin-node
binary (bitcoin -m
) for functional tests in two of them.bitcoin-node
andbitcoin-gui
are added toMaintenance.cmake
(since they're now in the release)capnp
by defaultThis PR doesn't need to do all of 3 things at once. However it's is simpler, avoids code churn (especially in CI), and probably less confusing to make all these changes in the same PR.
Windows is not supported yet, so
ENABLE_IPC
is off by default for it. It can be enabled after #32387.The initial main use case for IPC is to enable experimental support for the Mining IPC interface. A working example of a Stratum v2 Template Provider client using this interface can be found here: Sjors#48.
See #31756 for discussion of when this should happen. Supersedes #30975.
Guix hashes: