[libcxx-commits] [libcxx] [libc++] Throw future_error in future.get() (PR #179409)
via libcxx-commits
libcxx-commits at lists.llvm.org
Fri Apr 24 02:17:44 PDT 2026
https://github.com/Ekkorus101 updated https://github.com/llvm/llvm-project/pull/179409
>From 11b1a5d2207e962f3aa8dfd3db0504777be03b92 Mon Sep 17 00:00:00 2001
From: zhangqingchun <zhangqingchun at bytedance.com>
Date: Thu, 23 Apr 2026 16:15:26 +0800
Subject: [PATCH] [libc++] Add future error for std::future::get()
Throw std::future_errc::no_state when calling get() on a future with no shared state.
Move the corresponding test to extensions/all/ since libstdc++ also implements this behavior.
---
libcxx/include/future | 4 +
libcxx/src/future.cpp | 2 +
.../futures.unique_future/get.pass.cpp | 94 +++++++++++++++++++
3 files changed, 100 insertions(+)
create mode 100644 libcxx/test/extensions/all/thread/futures/futures.unique_future/get.pass.cpp
diff --git a/libcxx/include/future b/libcxx/include/future
index 6bd836afa04e8..3874d1036857f 100644
--- a/libcxx/include/future
+++ b/libcxx/include/future
@@ -985,6 +985,8 @@ future<_Rp>::~future() {
template <class _Rp>
_Rp future<_Rp>::get() {
+ if (__state_ == nullptr)
+ std::__throw_future_error(future_errc::no_state);
unique_ptr<__shared_count, __release_shared_count> __guard(__state_);
__assoc_state<_Rp>* __s = __state_;
__state_ = nullptr;
@@ -1052,6 +1054,8 @@ future<_Rp&>::~future() {
template <class _Rp>
_Rp& future<_Rp&>::get() {
+ if (__state_ == nullptr)
+ std::__throw_future_error(future_errc::no_state);
unique_ptr<__shared_count, __release_shared_count> __guard(__state_);
__assoc_state<_Rp&>* __s = __state_;
__state_ = nullptr;
diff --git a/libcxx/src/future.cpp b/libcxx/src/future.cpp
index 7bba635e9006f..ad9ec2ef01a3d 100644
--- a/libcxx/src/future.cpp
+++ b/libcxx/src/future.cpp
@@ -132,6 +132,8 @@ future<void>::~future() {
}
void future<void>::get() {
+ if (__state_ == nullptr)
+ std::__throw_future_error(future_errc::no_state);
unique_ptr<__shared_count, __release_shared_count> __(__state_);
__assoc_sub_state* __s = __state_;
__state_ = nullptr;
diff --git a/libcxx/test/extensions/all/thread/futures/futures.unique_future/get.pass.cpp b/libcxx/test/extensions/all/thread/futures/futures.unique_future/get.pass.cpp
new file mode 100644
index 0000000000000..3d4b4a2409c44
--- /dev/null
+++ b/libcxx/test/extensions/all/thread/futures/futures.unique_future/get.pass.cpp
@@ -0,0 +1,94 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// UNSUPPORTED: no-threads
+// UNSUPPORTED: c++03
+// XFAIL: availability-no_exceptions
+
+// <future>
+
+// class future<R>
+
+// R future::get();
+// R& future<R&>::get();
+// void future<void>::get();
+
+#include <future>
+#include <cassert>
+
+int main(int, char**)
+{
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ {
+ std::future<int> f;
+ try {
+ (void)f.get();
+ assert(false);
+ } catch (const std::future_error& e) {
+ assert(e.code() == std::make_error_code(std::future_errc::no_state));
+ }
+ }
+ {
+ std::promise<int> p;
+ std::future<int> f = p.get_future();
+ p.set_value(3);
+ (void)f.get();
+ try {
+ (void)f.get();
+ assert(false);
+ } catch (const std::future_error& e) {
+ assert(e.code() == std::make_error_code(std::future_errc::no_state));
+ }
+ }
+ {
+ std::future<int&> f;
+ try {
+ (void)f.get();
+ assert(false);
+ } catch (const std::future_error& e) {
+ assert(e.code() == std::make_error_code(std::future_errc::no_state));
+ }
+ }
+ {
+ std::promise<int&> p;
+ std::future<int&> f = p.get_future();
+ int j_val = 5;
+ p.set_value(j_val);
+ (void)f.get();
+ try {
+ (void)f.get();
+ assert(false);
+ } catch (const std::future_error& e) {
+ assert(e.code() == std::make_error_code(std::future_errc::no_state));
+ }
+ }
+ {
+ std::future<void> f;
+ try {
+ (void)f.get();
+ assert(false);
+ } catch (const std::future_error& e) {
+ assert(e.code() == std::make_error_code(std::future_errc::no_state));
+ }
+ }
+ {
+ std::promise<void> p;
+ std::future<void> f = p.get_future();
+ p.set_value();
+ (void)f.get();
+ try {
+ (void)f.get();
+ assert(false);
+ } catch (const std::future_error& e) {
+ assert(e.code() == std::make_error_code(std::future_errc::no_state));
+ }
+ }
+#endif
+
+ return 0;
+}
More information about the libcxx-commits
mailing list