[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