[libc-commits] [libc] [libc] Add optional::value_or and clean up if_nameindex_test TODOs (PR #213682)
via libc-commits
libc-commits at lists.llvm.org
Mon Aug 3 07:15:42 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-libc
Author: Pavel Labath (labath)
<details>
<summary>Changes</summary>
I went through the TODOs in if_nameindex_test.cpp:
- string::operator+=(string_view) was already present in string.h (added in #<!-- -->210895), so I removed the append_bytes helper and switched to operator+= directly.
- I added value_or (const & and && overloads) to cpp::optional and added a test suite for it in optional_test.cpp.
- I replaced pop_front_or with pop_front returning optional<T> and inlined the .value_or(...) calls in the fake network policy.
- Updated the CMake dependencies to account for the new optional usage.
Assisted by Gemini.
---
Full diff: https://github.com/llvm/llvm-project/pull/213682.diff
5 Files Affected:
- (modified) libc/src/__support/CPP/CMakeLists.txt (+3)
- (modified) libc/src/__support/CPP/optional.h (+12)
- (modified) libc/test/src/__support/CPP/optional_test.cpp (+19)
- (modified) libc/test/src/net/linux/CMakeLists.txt (+1-1)
- (modified) libc/test/src/net/linux/if_nameindex_test.cpp (+10-18)
``````````diff
diff --git a/libc/src/__support/CPP/CMakeLists.txt b/libc/src/__support/CPP/CMakeLists.txt
index 5b89257418732..e11d823333b25 100644
--- a/libc/src/__support/CPP/CMakeLists.txt
+++ b/libc/src/__support/CPP/CMakeLists.txt
@@ -114,6 +114,9 @@ add_header_library(
optional
HDRS
optional.h
+ DEPENDS
+ .type_traits
+ .utility
)
add_header_library(
diff --git a/libc/src/__support/CPP/optional.h b/libc/src/__support/CPP/optional.h
index aed2269db1b11..0d52badf831ed 100644
--- a/libc/src/__support/CPP/optional.h
+++ b/libc/src/__support/CPP/optional.h
@@ -131,6 +131,18 @@ template <typename T> class optional {
LIBC_INLINE constexpr T &&operator*() && {
return move(storage.stored_value);
}
+
+ template <typename U>
+ LIBC_INLINE constexpr T value_or(U &&default_value) const & {
+ return has_value() ? storage.stored_value
+ : static_cast<T>(forward<U>(default_value));
+ }
+
+ template <typename U>
+ LIBC_INLINE constexpr T value_or(U &&default_value) && {
+ return has_value() ? move(storage.stored_value)
+ : static_cast<T>(forward<U>(default_value));
+ }
};
} // namespace cpp
diff --git a/libc/test/src/__support/CPP/optional_test.cpp b/libc/test/src/__support/CPP/optional_test.cpp
index b2c8545eb36f0..4a6ebd8d51d7f 100644
--- a/libc/test/src/__support/CPP/optional_test.cpp
+++ b/libc/test/src/__support/CPP/optional_test.cpp
@@ -80,3 +80,22 @@ TEST(LlvmLibcOptionalTest, Tests) {
ASSERT_EQ(arrow_num, 11);
arrow_test.reset();
}
+
+TEST(LlvmLibcOptionalTest, ValueOr) {
+ optional<int> opt_empty;
+ EXPECT_EQ(opt_empty.value_or(42), 42);
+ optional<int> opt_full(10);
+ EXPECT_EQ(opt_full.value_or(42), 10);
+ EXPECT_EQ(optional<int>(100).value_or(42), 100);
+ EXPECT_EQ(optional<int>().value_or(42), 42);
+
+ const optional<int> opt_const_empty;
+ EXPECT_EQ(opt_const_empty.value_or(42), 42);
+ const optional<int> opt_const_full(10);
+ EXPECT_EQ(opt_const_full.value_or(42), 10);
+
+ optional<long> opt_long_empty;
+ EXPECT_EQ(opt_long_empty.value_or(42), 42L);
+ optional<long> opt_long_full(100L);
+ EXPECT_EQ(opt_long_full.value_or(42), 100L);
+}
diff --git a/libc/test/src/net/linux/CMakeLists.txt b/libc/test/src/net/linux/CMakeLists.txt
index 08f288e2256f6..22f4c2429805e 100644
--- a/libc/test/src/net/linux/CMakeLists.txt
+++ b/libc/test/src/net/linux/CMakeLists.txt
@@ -38,11 +38,11 @@ add_libc_unittest(
libc.hdr.types.socklen_t
libc.hdr.types.ssize_t
libc.hdr.types.struct_if_nameindex
+ libc.src.__support.CPP.optional
libc.src.__support.CPP.span
libc.src.__support.CPP.string
libc.src.__support.CPP.string_view
libc.src.__support.CPP.tuple
- libc.src.__support.CPP.type_traits
libc.src.__support.error_or
libc.src.__support.fixedvector
libc.src.net.if_freenameindex
diff --git a/libc/test/src/net/linux/if_nameindex_test.cpp b/libc/test/src/net/linux/if_nameindex_test.cpp
index ef5022b6420dc..1285f967ad0b1 100644
--- a/libc/test/src/net/linux/if_nameindex_test.cpp
+++ b/libc/test/src/net/linux/if_nameindex_test.cpp
@@ -16,11 +16,11 @@
#include "hdr/types/socklen_t.h"
#include "hdr/types/ssize_t.h"
#include "hdr/types/struct_if_nameindex.h"
+#include "src/__support/CPP/optional.h"
#include "src/__support/CPP/span.h"
#include "src/__support/CPP/string.h"
#include "src/__support/CPP/string_view.h"
#include "src/__support/CPP/tuple.h"
-#include "src/__support/CPP/type_traits/type_identity.h"
#include "src/__support/error_or.h"
#include "src/__support/fixedvector.h"
#include "src/net/if_freenameindex.h"
@@ -38,18 +38,17 @@ using LIBC_NAMESPACE::Error;
using LIBC_NAMESPACE::ErrorOr;
using LIBC_NAMESPACE::FixedVector;
using LIBC_NAMESPACE::cpp::get;
+using LIBC_NAMESPACE::cpp::nullopt;
+using LIBC_NAMESPACE::cpp::optional;
using LIBC_NAMESPACE::cpp::span;
using LIBC_NAMESPACE::cpp::string;
using LIBC_NAMESPACE::cpp::string_view;
using LIBC_NAMESPACE::cpp::tuple;
-// TODO: Add optional::value_or, then return optional<T>.
template <typename T, size_t CAPACITY>
-static T
-pop_front_or(FixedVector<T, CAPACITY> &vec,
- typename LIBC_NAMESPACE::cpp::type_identity<T>::type default_val) {
+static optional<T> pop_front(FixedVector<T, CAPACITY> &vec) {
if (vec.empty())
- return default_val;
+ return nullopt;
// TODO: Add front() and erase() to FixedVector, then clean this up.
T first = vec[0];
for (size_t i = 1; i < vec.size(); ++i)
@@ -58,13 +57,6 @@ pop_front_or(FixedVector<T, CAPACITY> &vec,
return first;
}
-// TODO: Add string::operator+=(string_view), then remove this helper.
-static void append_bytes(string &str, const void *data, size_t len) {
- size_t old_size = str.size();
- str.resize(old_size + len);
- LIBC_NAMESPACE::inline_memcpy(str.data() + old_size, data, len);
-}
-
namespace {
struct FakeNetworkSyscallPolicyData {
@@ -86,21 +78,21 @@ struct FakeNetworkSyscallPolicyData {
template <FakeNetworkSyscallPolicyData *DATA> struct FakeNetworkSyscallPolicy {
static ErrorOr<int> socket(int domain, int type, int protocol) {
DATA->socket_calls.push_back(tuple<int, int, int>(domain, type, protocol));
- return pop_front_or(DATA->socket_results, Error(ENFILE));
+ return pop_front(DATA->socket_results).value_or(Error(ENFILE));
}
static ErrorOr<ssize_t> sendto(int fd, const void *buf, size_t len, int flags,
const struct sockaddr *, socklen_t) {
DATA->sendto_calls.push_back(tuple<int, size_t, int>(fd, len, flags));
- append_bytes(DATA->sendto_data, buf, len);
- return pop_front_or(DATA->sendto_results, static_cast<ssize_t>(len));
+ DATA->sendto_data += string_view(static_cast<const char *>(buf), len);
+ return pop_front(DATA->sendto_results).value_or(static_cast<ssize_t>(len));
}
static ErrorOr<ssize_t> recvfrom(int fd, void *buf, size_t len, int flags,
struct sockaddr *, socklen_t *) {
DATA->recv_calls.push_back(tuple<int, size_t, int>(fd, len, flags));
ErrorOr<span<const uint8_t>> chunk =
- pop_front_or(DATA->recv_results, span<const uint8_t>());
+ pop_front(DATA->recv_results).value_or(span<const uint8_t>());
if (!chunk.has_value())
return Error(chunk.error());
if (chunk->size() > len)
@@ -111,7 +103,7 @@ template <FakeNetworkSyscallPolicyData *DATA> struct FakeNetworkSyscallPolicy {
static ErrorOr<int> close(int fd) {
DATA->close_calls.push_back(fd);
- return pop_front_or(DATA->close_results, 0);
+ return pop_front(DATA->close_results).value_or(0);
}
};
``````````
</details>
https://github.com/llvm/llvm-project/pull/213682
More information about the libc-commits
mailing list