Skip to content
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

feat(build): Switch to use C++20 standard #10866

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

czentgr
Copy link
Collaborator

@czentgr czentgr commented Aug 27, 2024

Fixes as a result:

  • fix warnings with deprecated usage of volatile variables - replace with std::atomic
  • replace usage of deprecated std::is_pod_v
  • fix deprecated usage of implicit capture of ‘this’ via ‘[=]’
  • fix ambiguity when calling == operator for LambdaTypedExpr
  • rearrange some link libraries order to prevent undefined symbols
  • handle AppleClang versions overloading operator<< for sys_seconds input
  • handle AppleClang format_to function ambiguity between fmt and system headers
  • remove std=c++17 from the setup helper script which influences the build
  • disable folly coroutine headers because the library is not built to support it

Resolves: #10814

@facebook-github-bot facebook-github-bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Aug 27, 2024
Copy link

netlify bot commented Aug 27, 2024

Deploy Preview for meta-velox canceled.

Name Link
🔨 Latest commit 33f0a8f
🔍 Latest deploy log https://app.netlify.com/sites/meta-velox/deploys/6757864bc0806900087e84e9

--numWaiting_;
--count_;
}
sem_.acquire();
Copy link
Contributor

@Yuhta Yuhta Aug 28, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the point to protect semaphore with a lock? This would cause deadlock

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I kept the previous behavior. There is a difference between the counting_semaphore and the mutex in how they work (what they protect - a semaphore can be changed by other threads, with the mutex this is prevented).
And so I used the counting_semaphore to replace the volatile counter (and the way it was triggered).
Because the mutex is used before (with its behavior) I didn't want to change the behavior and allow new race conditions. This can be revisited as a TODO.

Copy link
Contributor

@Yuhta Yuhta Aug 28, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then you probably should not change it, and add the reason to comment why this cannot be a drop-in replacement for std:: counting_semaphore. The change now will cause deadlock.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can undo it and remove the volatile keyword for the members - which is what the complaint of the compiler is.

When I made the change I thought about the behavior change. The fact that a mutex was always taken hasn't changed. I understood that using the counting_semaphore is a bit more permissive in terms of access. The fact that the mutex is taken still allows only a single thread to access it at any given time. But it doesn't change the counting.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A thread blocked on acquire would hold the lock and block another thread to call release.
condition_variable::wait is releasing the lock in the current code, that's a behavior change.

@zuyu
Copy link
Contributor

zuyu commented Aug 31, 2024

Fyi, happened to see that the following file also contains many hard-coded -std=c++17:

-DCMAKE_CXX_STANDARD=17 \

@zuyu
Copy link
Contributor

zuyu commented Aug 31, 2024

Also, Velox codebase has tens of the std::shared_ptr<T>::unique usages, but it was deprecated in C++17 and removed in C++20 1. I am NOT sure if you would also encounter this issue.

Footnotes

  1. https://en.cppreference.com/w/cpp/memory/shared_ptr/unique

@czentgr
Copy link
Collaborator Author

czentgr commented Sep 10, 2024

Both Clang15 and gcc12 (will test gcc11) look good. No major problems, just a few things here and there.

The bigger issue is macOS apple-clang 15.
The timezone database files overload the << operators and it is causing issues.

Looks like the SDK is providing a function already that is not ambiguous because the date.h also implements one with one difference which is using the reference operator for the second argument.

/Library/Developer/CommandLineTools/SDKs/MacOSX14.4.sdk/usr/include/c++/v1/__chrono/ostream.h:46:1: note: candidate function [with _CharT = char, _Traits = std::char_traits<char>, _Duration = std::chrono::duration<long long>]
operator<<(basic_ostream<_CharT, _Traits>& __os, const sys_time<_Duration> __tp) {
^
/Users/czentgr/gitspace/velox/velox/external/date/date.h:3981:1: note: candidate function [with CharT = char, Traits = std::char_traits<char>, Duration = std::chrono::duration<long long>]
operator<<(std::basic_ostream<CharT, Traits>& os, const sys_time<Duration>& tp)
^

And it doesn't know which one to use. This affects a few of these.

I'm thinking to try and using the SDK functions - ifdef __APPLE__ out the date function overloads and see how it goes.

Edit: This is a bigger problem. As the CI pipeline shows the macOS 13 build failed because the operator<< is not overloaded for the types - that this function defines it for.
The difference is the AppleClang version 15.0.0.15000100 (Xcode_15.2). The macOS 14 uses the same version that I have locally 15.0.0.15000309 (Xcode_15.4).
I used the __apple_build_version to exclude the build for the newer version.

@czentgr
Copy link
Collaborator Author

czentgr commented Sep 10, 2024

@zuyu

Fyi, happened to see that the following file also contains many hard-coded -std=c++17:

Yes. This is ok and will actually be removed (there is a PR that does this I believe). This setting is used to compile the dependencies. This doesn't affect the Velox build directly so it doesn't change anything dne here. All that this PR will do is given a set of dependencies build the Velox code (not its dependencies) with C++20. Some of the dependencies likely don't support C++20 just yet.

Edit: It is true that this is picked up in the CMakeLists.txt because it is reading it from the file too. But the version is also set using the CMake option and so the -std appears twice in the command. The latest occurrence of the option is used by the compiler. That was one of the problems when one of the dependencies had changed their default to C++20 and it caused build issues (which was then reverted again in their project).

@czentgr
Copy link
Collaborator Author

czentgr commented Sep 10, 2024

@zuyu

Also, Velox codebase has tens of the std::shared_ptr::unique usages, but it was deprecated in C++17 and removed in C++20 1. I am NOT sure if you would also encounter this issue.

I have not actually. I'm fixing some errors that are reported as deprecated usages but I haven't seen anything fail because of this particular issue yet. Perhaps something to cleanup later.

Edit: Do you have an example for this? I looked and didn't find an instance of this usage. Because it was deprecated in C++17 it should have failed the build then. deprecated messages are errors in the build and new ones come up when upping the C++ standard that I'm addressing in this PR.

@czentgr czentgr force-pushed the cz_c++20_support branch 4 times, most recently from e05dd84 to 053e13b Compare September 11, 2024 00:23
@czentgr
Copy link
Collaborator Author

czentgr commented Sep 11, 2024

So the compiler bug in gcc 12.2.1 is pretty bad because it affects third-party headers such as gtest:

    inlined from ‘static void testing::internal::ProtobufPrinter::PrintValue(const T&, std::ostream*) [with T = facebook::velox::dwrf::proto::RowIndex; <template-parameter-1-2> = void]’ at /root/oss/velox/_build/release/_deps/gtest-src/googletest/include/gtest/gtest-printers.h:235:18:
/opt/rh/gcc-toolset-12/root/usr/include/c++/12/bits/char_traits.h:431:56: error: ‘void* __builtin_memcpy(void*, const void*, long unsigned int)’ accessing 9223372036854775810 or more bytes at offsets [2, 9223372036854775807] and 1 may overlap up to 9223372036854775813 bytes at offset -3 [-Werror=restrict]
  431 |         return static_cast<char_type*>(__builtin_memcpy(__s1, __s2, __n));
      |

with this code

    if (pretty_str.length() > kProtobufOneLinerMaxLength) {
      pretty_str = "\n" + value.DebugString();
    }
    *os << ("<" + pretty_str + ">");
  }

Obviously gtest hasn't changed this code. So the only way to address it is by patching. In this case gtest is built as a bundle so it could be done but if we get it from a header of a pre-installed dependency - well there is no workaround. The only way is to upgrade gcc12 or switch to Clang completely.

The other fun part is that the bug only affects release builds. With debug mode the error does not occur.

@czentgr czentgr force-pushed the cz_c++20_support branch 2 times, most recently from 1277d7e to af0b130 Compare September 12, 2024 05:03
@@ -63,8 +63,8 @@ class Semaphore {
private:
std::mutex mutex_;
std::condition_variable cv_;
volatile int32_t count_;
volatile int32_t numWaiting_{0};
std::atomic<int32_t> count_;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can just remove the volatile, these are already fully protected by the mutex.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@majetideepak was concerned that without volatile some code might be optimized away that existed previously. There must have been some reason to use it before. So I changed it to use atomic to prevent any issue as this is the recommended change for situations like this.

Copy link
Contributor

@Yuhta Yuhta Sep 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With modern compiler and CPU volatile is not needed. The only case I needed it in my career is in CUDA.

Copy link
Collaborator Author

@czentgr czentgr Sep 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you. I defer to you on this. I have never used it either that I remember. I assume there was some reason the original author used it. Given we do have mutex protection single threaded access is guaranteed. I'm removing the std::atomic use here.

--numWaiting_;
--count_;
}
sem_.acquire();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A thread blocked on acquire would hold the lock and block another thread to call release.
condition_variable::wait is releasing the lock in the current code, that's a behavior change.

@czentgr czentgr force-pushed the cz_c++20_support branch 2 times, most recently from 91b6685 to cc39c0f Compare September 17, 2024 14:14
@czentgr
Copy link
Collaborator Author

czentgr commented Sep 17, 2024

The last remaining issue is a segv in velox_functions_remote_client_test.

The following tests FAILED:
	328 - velox_functions_remote_client_test (SEGFAULT)

The stack trace shows the issue occurs in folly when the ThriftServer is starting up.

Thread 22 "ThriftSrv-pri3-" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7fffaa7fc640 (LWP 498913)]
std::__uniq_ptr_impl<std::vector<std::unique_ptr<folly::futures::detail::DeferredExecutor, folly::futures::detail::UniqueDeleter>, std::allocator<std::unique_ptr<folly::futures::detail::DeferredExecutor, folly::futures::detail::UniqueDeleter> > >, std::default_delete<std::vector<std::unique_ptr<folly::futures::detail::DeferredExecutor, folly::futures::detail::UniqueDeleter>, std::allocator<std::unique_ptr<folly::futures::detail::DeferredExecutor, folly::futures::detail::UniqueDeleter> > > > >::_M_ptr (this=0x59) at /opt/rh/gcc-toolset-12/root/usr/include/c++/12/bits/unique_ptr.h:191
191           pointer    _M_ptr() const noexcept { return std::get<0>(_M_t); }
Missing separate debuginfos, use: dnf debuginfo-install libdwarf-0.3.4-1.el9.1.x86_64 libgsasl-1.10.0-3.el9.x86_64 libidn-1.38-4.el9.x86_64 libntlm-1.6-4.el9.x86_64 libsodium-1.0.18-8.el9.x86_64 re2-20211101-20.el9.x86_64
::UniqueDeleter>, std::allocator<std::unique_ptr<folly::futures::detail::DeferredExecutor, folly::futures::detail::UniqueDeleter> > >, std::default_delete<std::vector<std::unique_ptr<folly::futures::detail::DeferredExecutor, folly::futures::detail::UniqueDeleter>, std::allocator<std::unique_ptr<folly::futures::detail::DeferredExecutor, folly::futures::detail::UniqueDeleter> > > > >::_M_ptr (this=0x59)
    at /opt/rh/gcc-toolset-12/root/usr/include/c++/12/bits/unique_ptr.h:191
#1  0x0000000005223778 in std::unique_ptr<std::vector<std::unique_ptr<folly::futures::detail::DeferredExecutor, folly::futures::detail::UniqueDeleter>, std::allocator<std::unique_ptr<folly::futures::detail::DeferredExecutor, folly::futures::detail::UniqueDeleter> > >, std::default_delete<std::vector<std::unique_ptr<folly::futures::detail::DeferredExecutor, folly::futures::detail::UniqueDeleter>, std::allocator<std::unique_ptr<folly::futures::detail::DeferredExecutor, folly::futures::detail::UniqueDeleter> > > > >::get (this=0x59)
    at /opt/rh/gcc-toolset-12/root/usr/include/c++/12/bits/unique_ptr.h:462
#2  0x0000000005222f90 in std::unique_ptr<std::vector<std::unique_ptr<folly::futures::detail::DeferredExecutor, folly::futures::detail::UniqueDeleter>, std::allocator<std::unique_ptr<folly::futures::detail::DeferredExecutor, folly::futures::detail::UniqueDeleter> > >, std::default_delete<std::vector<std::unique_ptr<folly::futures::detail::DeferredExecutor, folly::futures::detail::UniqueDeleter>, std::allocator<std::unique_ptr<folly::futures::detail::DeferredExecutor, folly::futures::detail::UniqueDeleter> > > > >::operator bool (this=0x59)
    at /opt/rh/gcc-toolset-12/root/usr/include/c++/12/bits/unique_ptr.h:479
#3  0x000000000521fc93 in folly::futures::detail::DeferredExecutor::setExecutor (this=0x1, executor=...,
    inlineUnsafe=false) at /root/oss/deps/folly/folly/futures/detail/Core.cpp:187
#4  0x0000000002d690f7 in folly::SemiFuture<folly::Unit>::via(folly::Executor::KeepAlive<folly::Executor>) && ()
#5  0x0000000002d69289 in folly::Future<folly::Unit> folly::futures::detail::chainExecutor<folly::Unit>(folly::Executor::KeepAlive<folly::Executor>, folly::SemiFuture<folly::Unit>&&) ()
#6  0x0000000004a13288 in folly::futures::detail::FutureBase<folly::Unit>::thenImplementation<folly::Future<folly::Unit>::thenTryInline<folly::SemiFuture<folly::Unit>::deferValue<apache::thrift::ThriftServer::callOnStartServing()::{lambda(folly::Unit)#1}>(apache::thrift::ThriftServer::callOnStartServing()::{lambda(folly::Unit)#1}&&) &&::{lambda(folly::Try<folly::Unit>&&)#1}>(apache::thrift::ThriftServer::callOnStartServing()::{lambda(folly::Unit)#1}&&) &&::{lambda(folly::Executor::KeepAlive<folly::Executor>&&, folly::Try<folly::Unit>&&)#1}, folly::futures::detail::tryExecutorCallableResult<folly::Unit, folly::Future<folly::Unit>::thenTryInline<folly::SemiFuture<folly::Unit>::deferValue<apache::thrift::ThriftServer::callOnStartServing()::{lambda(folly::Unit)#1}>(apache::thrift::ThriftServer::callOnStartServing()::{lambda(folly::Unit)#1}&&) &&::{lambda(folly::Try<folly::Unit>&&)#1}>(apache::thrift::ThriftServer::callOnStartServing()::{lambda(folly::Unit)#1}&&) &&::{lambda(folly::Executor::KeepAlive<folly::Executor>&&, folly::Try<folly::Unit>&&)#1}> >(apache::thrift::ThriftServer::callOnStartServing()::{lambda(folly::Unit)#1}&&, folly::futures::detail::tryExecutorCallableResult<folly::Unit, folly::Future<folly::Unit>::thenTryInline<folly::SemiFuture<folly::Unit>::deferValue<apache::thrift::ThriftServer::callOnStartServing()::{lambda(folly::Unit)#1}>(apache::thrift::ThriftServer::callOnStartServing()::{lambda(folly::Unit)#1}&&) &&::{lambda(folly::Try<folly::Unit>&&)#1}>(apache::thrift::ThriftServer::callOnStartServing()::{lambda(folly::Unit)#1}&&) &&::{lambda(folly::Executor::KeepAlive<folly::Executor>&&, folly::Try<folly::Unit>&&)#1}>, folly::futures::detail::InlineContinuation)::{lambda(folly::Executor::KeepAlive<folly::Executor>&&, folly::Try<folly::Unit>&&)#1}::operator()(folly::Executor::KeepAlive<folly::Executor>&&, folly::Try<folly::Unit>&&) ()
#7  0x0000000004a16ff7 in folly::futures::detail::Core<folly::Unit>::setCallback<folly::futures::detail::FutureBase<folly::Unit>::thenImplementation<folly::Future<folly::Unit>::thenTryInline<folly::SemiFuture<folly::Unit>::deferValue<apache::thrift::ThriftServer::callOnStartServing()::{lambda(folly::Unit)#1}>(apache::thrift::ThriftServer::callOnStartServing()::{lambda(folly::Unit)#1}&&) &&::{lambda(folly::Try<folly::Unit>&&)#1}>(apache::thrift::ThriftServer::callOnStartServing()::{lambda(folly::Unit)#1}&&) &&::{lambda(folly::Executor::KeepAlive<folly::Executor>&&, folly::Try<folly::Unit>&&)#1}, folly::futures::detail::tryExecutorCallableResult<folly::Unit, folly::Future<folly::Unit>::thenTryInline<folly::SemiFuture<folly::Unit>::deferValue<apache::thrift::ThriftServer::callOnStartServing()::{lambda(folly::Unit)#1}>(apache::thrift::ThriftServer::callOnStartServing()::{lambda(folly::Unit)#1}&&) &&::{lambda(folly::Try<folly::Unit>&&)#1}>(apache::thrift::ThriftServer::callOnStartServing()::{lambda(folly::Unit)#1}&&) &&::{lambda(folly::Executor::KeepAlive<folly::Executor>&&, folly::Try<folly::Unit>&&)#1}> >(apache::thrift::ThriftServer::callOnStartServing()::{lambda(folly::Unit)#1}&&, folly::futures::detail::tryExecutorCallableResult<folly::Unit, folly::Future<folly::Unit>::thenTryInline<folly::SemiFuture<folly::Unit>::deferValue<apache::thrift::ThriftServer::callOnStartServing()::{lambda(folly::Unit)#1}>(apache::thrift::ThriftServer::callOnStartServing()::{lambda(folly::Unit)#1}&&) &&::{lambda(folly::Try<folly::Unit>&&)#1}>(apache::thrift::ThriftServer::callOnStartServing()::{lambda(folly::Unit)#1}&&) &&::{lambda(folly::Executor::KeepAlive<folly::Executor>&&, folly::Try<folly::Unit>&&)#1}>, folly::futures::detail::--Type <RET> for more, q to qu
--Type <RET> for more, q to quit, c to continue without paging--
InlineContinuation)::{lambda(folly::Executor::KeepAlive<folly::Executor>&&, folly::Try<folly::Unit>&&)#1}>(apache::thrift::ThriftServer::callOnStartServing()::{lambda(folly::Unit)#1}&&, std::shared_ptr<folly::RequestContext>&&, folly::futures::detail::InlineContinuation)::{lambda(folly::futures::detail::CoreBase&, folly::Executor::KeepAlive<folly::Executor>&&, folly::exception_wrapper*)#1}::operator()(folly::futures::detail::CoreBase&, folly::Executor::KeepAlive<folly::Executor>&&, folly::exception_wrapper*) ()
#8  0x0000000004a180a5 in void folly::detail::function::call_<folly::futures::detail::Core<folly::Unit>::setCallback<folly::futures::detail::FutureBase<folly::Unit>::thenImplementation<folly::Future<folly::Unit>::thenTryInline<folly::SemiFuture<folly::Unit>::deferValue<apache::thrift::ThriftServer::callOnStartServing()::{lambda(folly::Unit)#1}>(apache::thrift::ThriftServer::callOnStartServing()::{lambda(folly::Unit)#1}&&) &&::{lambda(folly::Try<folly::Unit>&&)#1}>(apache::thrift::ThriftServer::callOnStartServing()::{lambda(folly::Unit)#1}&&) &&::{lambda(folly::Executor::KeepAlive<folly::Executor>&&, folly::Try<folly::Unit>&&)#1}, folly::futures::detail::tryExecutorCallableResult<folly::Unit, folly::Future<folly::Unit>::thenTryInline<folly::SemiFuture<folly::Unit>::deferValue<apache::thrift::ThriftServer::callOnStartServing()::{lambda(folly::Unit)#1}>(apache::thrift::ThriftServer::callOnStartServing()::{lambda(folly::Unit)#1}&&) &&::{lambda(folly::Try<folly::Unit>&&)#1}>(apache::thrift::ThriftServer::callOnStartServing()::{lambda(folly::Unit)#1}&&) &&::{lambda(folly::Executor::KeepAlive<folly::Executor>&&, folly::Try<folly::Unit>&&)#1}> >(apache::thrift::ThriftServer::callOnStartServing()::{lambda(folly::Unit)#1}&&, folly::futures::detail::tryExecutorCallableResult<folly::Unit, folly::Future<folly::Unit>::thenTryInline<folly::SemiFuture<folly::Unit>::deferValue<apache::thrift::ThriftServer::callOnStartServing()::{lambda(folly::Unit)#1}>(apache::thrift::ThriftServer::callOnStartServing()::{lambda(folly::Unit)#1}&&) &&::{lambda(folly::Try<folly::Unit>&&)#1}>(apache::thrift::ThriftServer::callOnStartServing()::{lambda(folly::Unit)#1}&&) &&::{lambda(folly::Executor::KeepAlive<folly::Executor>&&, folly::Try<folly::Unit>&&)#1}>, folly::futures::detail::InlineContinuation)::{lambda(folly::Executor::KeepAlive<folly::Executor>&&, folly::Try<folly::Unit>&&)#1}>(apache::thrift::ThriftServer::callOnStartServing()::{lambda(folly::Unit)#1}&&, std::shared_ptr<folly::RequestContext>&&, folly::futures::detail::InlineContinuation)::{lambda(folly::futures::detail::CoreBase&, folly::Executor::KeepAlive<folly::Executor>&&, folly::exception_wrapper*)#1}, true, false, void, folly::futures::detail::CoreBase&, folly::Executor::KeepAlive<folly::Executor>&&, folly::exception_wrapper*>(folly::futures::detail::CoreBase&, folly::Executor::KeepAlive<folly::Executor>&&, folly::exception_wrapper*, folly::detail::function::Data&) ()
#9  0x00000000052233d4 in folly::detail::function::FunctionTraits<void (folly::futures::detail::CoreBase&, folly::Executor::KeepAlive<folly::Executor>&&, folly::exception_wrapper*)>::operator()(folly::futures::detail::CoreBase&, folly::Executor::KeepAlive<folly::Executor>&&, folly::exception_wrapper*) (this=0x7fffd400e020, args#0=..., args#1=...,
    args#2=0x0) at /root/oss/deps/folly/folly/Function.h:370
#10 0x0000000005221884 in operator() (__closure=0x7fffd4032150, ka=...)
    at /root/oss/deps/folly/folly/futures/detail/Core.cpp:621
#11 0x00000000052227ba in folly::detail::function::call_<folly::futures::detail::CoreBase::doCallback(folly::Executor::KeepAlive<>&&, folly::futures::detail::State)::<lambda(folly::Executor::KeepAlive<>&&)>, true, false, void, folly::Executor::KeepAlive<folly::Executor>&&>(folly::detail::function::Data &) (p=...)
    at /root/oss/deps/folly/folly/Function.h:341
#12 0x0000000005222c9e in folly::detail::function::FunctionTraits<void (folly::Executor::KeepAlive<folly::Executor>&&)>::operator()(folly::Executor::KeepAlive<folly::Executor>&&) (this=0x7fffd4032150, args#0=...)
    at /root/oss/deps/folly/folly/Function.h:370
#13 0x0000000005222cdc in folly::Executor::KeepAlive<folly::Executor>::add<folly::Function<void (folly::Executor::KeepAlive<folly::Executor>&&)> >(folly::Function<void (folly::Executor::KeepAlive<folly::Executor>&&)>&&) &&::{lambda()#1}::operator()() (__closure=0x7fffd4032140) at /root/oss/deps/folly/folly/Executor.h:187
#14 0x0000000005223b85 in folly::detail::function::call_<folly::Executor::KeepAlive<folly::Executor>::add<folly::Function<void (folly::Executor::KeepAlive<folly::Executor>&&)> >(folly::Function<void (folly::Executor::KeepAlive<folly::Executor>&&)>&&) &&::{lambda()#1}, false, false, void>(, folly::detail::function::Data&) (p=...)
    at /root/oss/deps/folly/folly/Function.h:341
#15 0x000000000493adeb in folly::detail::function::FunctionTraits<void ()>::operator()() (this=0x7fffd40321b0)
    at /root/oss/deps/folly/folly/Function.h:370
#16 0x0000000004952979 in apache::thrift::concurrency::FunctionRunner::run() ()
#17 0x0000000004ed0673 in apache::thrift::concurrency::ThreadManager::Task::run()::{lambda()#1}::operator()() const
    ()
#18 0x0000000004ed06fc in apache::thrift::concurrency::ThreadManager::Task::run() ()
#19 0x0000000004ed2257 in apache::thrift::concurrency::ThreadManager::Impl::Worker::run() ()
#20 0x0000000004ec0f47 in apache::thrift::concurrency::PthreadThread::threadMain(void*) ()
#21 0x00007ffff6489c52 in start_thread (arg=<optimized out>) at pthread_create.c:443
--Type <RET> for more, q to quit, c to continue without paging--
#22 0x00007ffff650ec80 in clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:81
(gdb) p $_siginfo
$1 = {si_signo = 11, si_errno = 0, si_code = 1, _sifields = {_pad = {89, 0 <repeats 27 times>}, _kill = {
      si_pid = 89, si_uid = 0}, _timer = {si_tid = 89, si_overrun = 0, si_sigval = {sival_int = 0,
        sival_ptr = 0x0}}, _rt = {si_pid = 89, si_uid = 0, si_sigval = {sival_int = 0, sival_ptr = 0x0}},
    _sigchld = {si_pid = 89, si_uid = 0, si_status = 0, si_utime = 0, si_stime = 0}, _sigfault = {si_addr = 0x59,
      _addr_lsb = 0, _addr_bnd = {_lower = 0x0, _upper = 0x0}}, _sigpoll = {si_band = 89, si_fd = 0}}}

I tried the same with the latest version of folly and fbthrift (v2024.09.16.00) and the SEGV went away. As a result we will be upgrading the FBOS dependencies.

Edit: This PR fixes the issue: #11018

@zuyu
Copy link
Contributor

zuyu commented Sep 21, 2024

@zuyu

Also, Velox codebase has tens of the std::shared_ptr::unique usages, but it was deprecated in C++17 and removed in C++20 1. I am NOT sure if you would also encounter this issue.

I have not actually. I'm fixing some errors that are reported as deprecated usages but I haven't seen anything fail because of this particular issue yet. Perhaps something to cleanup later.

Edit: Do you have an example for this? I looked and didn't find an instance of this usage. Because it was deprecated in C++17 it should have failed the build then. deprecated messages are errors in the build and new ones come up when upping the C++ standard that I'm addressing in this PR.

I did not remember since when I encountered the build issue related to deprecated shared_ptr::unique on macOS, but I guess it happened since upgrading to macOS 15. And currently I'm on macOS 15.1 beta w/ XCode 16.1 beta.

$ cc --version
Apple clang version 16.0.0 (clang-1600.0.26.3)
Target: arm64-apple-darwin24.1.0
Thread model: posix
InstalledDir: /Applications/Xcode-beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

velox $ make debug
velox/velox/vector/BaseVector.cpp:602:14: error: 'unique' is deprecated [-Werror,-Wdeprecated-declarations]
  602 |   if (result.unique() && !isUnknownType) {
      |              ^
/Applications/Xcode-beta.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.1.sdk/usr/include/c++/v1/__memory/shared_ptr.h:730:3: note: 'unique' has been explicitly marked deprecated here
  730 |   _LIBCPP_DEPRECATED_IN_CXX17 _LIBCPP_HIDE_FROM_ABI bool unique() const _NOEXCEPT { return use_count() == 1; }
      |   ^
/Applications/Xcode-beta.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.1.sdk/usr/include/c++/v1/__config:1022:41: note: expanded from macro '_LIBCPP_DEPRECATED_IN_CXX17'
 1022 | #    define _LIBCPP_DEPRECATED_IN_CXX17 _LIBCPP_DEPRECATED
      |                                         ^
/Applications/Xcode-beta.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.1.sdk/usr/include/c++/v1/__config:995:49: note: expanded from macro '_LIBCPP_DEPRECATED'
  995 | #      define _LIBCPP_DEPRECATED __attribute__((__deprecated__))
      |                                                 ^

@czentgr
Copy link
Collaborator Author

czentgr commented Oct 28, 2024

Waiting on resolution to #11318.

@czentgr czentgr force-pushed the cz_c++20_support branch 4 times, most recently from e8b45ea to 0573605 Compare November 15, 2024 23:25
@czentgr czentgr changed the title [WIP] Switch to use C++20 standard [WIP] feat(build): Switch to use C++20 standard Nov 15, 2024
@czentgr czentgr changed the title [WIP] feat(build): Switch to use C++20 standard feat(build): Switch to use C++20 standard Nov 18, 2024
@czentgr czentgr marked this pull request as ready for review November 18, 2024 16:35
@czentgr czentgr requested a review from Yuhta November 18, 2024 16:36
@czentgr
Copy link
Collaborator Author

czentgr commented Nov 18, 2024

The only failure in the CI pipeline is the performance test for a specific cast function showing a regression.

The try_cast(empty as date/timestamp/integer) expression is slower than before and is now in the same time range as try(cast(empty as date/timestamp/integer)).

Copy link
Collaborator

@assignUser assignUser left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CMake looks good.

Comment on lines +297 to +315
# For C++20 support we need GNU GCC11 (or later versions) or Clang/AppleClang 15
# (or later versions) to get support for the used features.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could also check for specific the specific features we need (see docs) this would make this portable to other compilers. What are we using that's only in gcc 11? Afaik 10 should have full(?) C++20 support?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gcc11 and clang15 have full C++20 support. gcc10 has only partial C++20 support. And one other reason was to set a minimum of compilers as a base from which we can build and check for features?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see there are a few features missing https://en.cppreference.com/w/cpp/compiler_support#cpp20

I am fine with setting a minimum version (should be documented in the readme if it's not) but this specific check will not trigger if someone uses the Intel compiler or something but I guess that would still throw an error once the compiler doesn't understand the C++20 flag so 🤷

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand now. I didn't think about the possibility of using other compilers (e.g. Intel) as we don't claim to support them.
In prestissimo we have a table with the compilers. I will add it to the Velox Readme too.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a table in the readme. Please take a look.

@czentgr czentgr force-pushed the cz_c++20_support branch 2 times, most recently from 15205c4 to d94a38e Compare November 20, 2024 17:48
@czentgr
Copy link
Collaborator Author

czentgr commented Nov 21, 2024

One of the consequences for this PR is that dependents will also need to build with C++20 or make a change to ignore warnings.
For example, when building Prestissimo with this branch it fails:

In file included from /Users/czentgr/gitspace/presto/presto-native-execution/velox/velox/exec/tests/utils/OperatorTestBase.h:27:
/Users/czentgr/gitspace/presto/presto-native-execution/velox/velox/vector/tests/utils/VectorMaker.h:148:50: error: explicit capture of 'this' with a capture default of '=' is a C++20 extension [-Werror,-Wc++20-extensions]
  148 |         std::make_unique<SimpleVectorLoader>([=, this](RowSet rowSet) {
      |                                                  ^

I can try to build Prestissimo with C++20 as well and see what will happen. not sure if turning off this warning is ok. We should be building Velox with C++20.

@assignUser do you have thoughts on this?

@assignUser
Copy link
Collaborator

assignUser commented Nov 22, 2024

@czentgr Well it's not as easy as bumping up cmake. What do we gain from using 20?

Are there specific features we want to use (std::chrono comes to mind) or is it more the general DX improvements?

What is the Velox userbase? Would they be ok with this? (Velox is to new to have legacy users?)

Are there things that would be blocked by requiring C++20 that we might want in the future (e.g. distribution via apt, which we probably don't?) .

@czentgr
Copy link
Collaborator Author

czentgr commented Nov 28, 2024

@assignUser There is a discussion item on why we want to go to C++20 outlining the reasons: #10692
Besides std::chrono there are also coroutines available (if folly is built to support this).

@assignUser
Copy link
Collaborator

@czentgr ah I missed that discussion, seems there is a well reasoned consensus with PLC involvement. Gluten seems to be fine with it as well so presto is the other major downstream user at this point. You and @majetideepak are working on that as well right? Checkinkg that it build with C++20 is probably common courtesy ^^

Copy link
Collaborator Author

@czentgr czentgr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@assignUser That's correct. @majetideepak and me would handle Prestissimo (and possibly might help with Gluten as well if needed). I'm going to see what would stop Prestissimo from upgrading to C++20.

CMakeLists.txt Outdated
endif()

set(KNOWN_WARNINGS
"-Wno-unused \
-Wno-unused-parameter \
-Wno-sign-compare \
-Wno-ignored-qualifiers \
-Wno-c++20-extensions \
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@assignUser This warning will prevent Prestissimo from failing. This is useful for now because when consumers use C++17 it will suppress the warnings of the Velox changes. If we build with C++20 in Velox itself this warning will not come out.
I don't think it is a problem because the compilers used in projects consuming Velox should adhere to the Velox minimum compiler version and they understand the syntax.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Meh this doesn't work for everything because upstream projects pull in headers which can elicit the warning when not build velox libraries. They would need to add this flag on their own or go to C++20.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Turns out we can turn off the deprecated capture this warning as it is not a generic deprecated messages (as I originally thought) with -Wdeprecated-this-capture. Prestissimo has a single occurrence of this.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think handling these warnings should be on the consumer, we would be hiding them without letting them know.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My thought was that we would remove this eventually when we update Gluten and Prestissimo as the main upstream consumers. But I can remove this. I can deal with the Velox update in Prestissimo once this merged and doesn't cause any trouble for someone.

Fixes as a result:
- fix warnings with deprecated usage of volatile variables - replace with std::atomic
- replace usage of deprecated std::is_pod_v
- turn on warning suppression for deprecated usage of implicit capture of ‘this’ via ‘[=]’
- fix ambiguity when calling == operator for LambdaTypedExpr
- rearrange some link libraries order to prevent undefined symbols
- handle AppleClang versions overloading operator<< for sys_seconds input
- handle AppleClang format_to function ambiguity between fmt and system headers
- remove std=c++17 from the setup helper script which influences the build
- disable folly coroutine headers because the library is not built to support it

If the implicit capture of this is fixed it causes upstream problems by issuing warning
c++20-extensions as upstream users are not yet on C++20.
Thus, adding to suppress the warning -Wdeprecated-this-capture for now.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add support for C++20
5 participants