[libc-commits] [libc] [libc][search] implement posix `lfind` function (PR #114692)
via libc-commits
libc-commits at lists.llvm.org
Thu Nov 7 11:03:21 PST 2024
https://github.com/duncpro updated https://github.com/llvm/llvm-project/pull/114692
>From 66c36e8c02f62349aed3e578ed8a26de158c2560 Mon Sep 17 00:00:00 2001
From: Duncan <duncpro at icloud.com>
Date: Sat, 2 Nov 2024 23:04:24 -0400
Subject: [PATCH 01/12] [libc][search] implement posix `lfind` function
---
libc/config/baremetal/arm/entrypoints.txt | 3 ++
libc/config/baremetal/riscv/entrypoints.txt | 3 ++
libc/config/darwin/arm/entrypoints.txt | 3 ++
libc/config/darwin/x86_64/entrypoints.txt | 3 ++
libc/config/linux/aarch64/entrypoints.txt | 1 +
libc/config/linux/arm/entrypoints.txt | 3 ++
libc/config/linux/riscv/entrypoints.txt | 1 +
libc/config/linux/x86_64/entrypoints.txt | 1 +
libc/config/windows/entrypoints.txt | 3 ++
libc/docs/libc_search.rst | 2 +-
libc/newhdrgen/yaml/search.yaml | 10 +++++
libc/spec/posix.td | 11 +++++
libc/src/search/CMakeLists.txt | 11 +++++
libc/src/search/lfind.cpp | 29 +++++++++++++
libc/src/search/lfind.h | 20 +++++++++
libc/test/src/search/CMakeLists.txt | 10 +++++
libc/test/src/search/lfind_test.cpp | 46 +++++++++++++++++++++
17 files changed, 159 insertions(+), 1 deletion(-)
create mode 100644 libc/src/search/lfind.cpp
create mode 100644 libc/src/search/lfind.h
create mode 100644 libc/test/src/search/lfind_test.cpp
diff --git a/libc/config/baremetal/arm/entrypoints.txt b/libc/config/baremetal/arm/entrypoints.txt
index 68030f7f1775b5..ae71ea9c327b63 100644
--- a/libc/config/baremetal/arm/entrypoints.txt
+++ b/libc/config/baremetal/arm/entrypoints.txt
@@ -26,6 +26,9 @@ set(TARGET_LIBC_ENTRYPOINTS
# errno.h entrypoints
libc.src.errno.errno
+ # search.h entrypoints
+ libc.src.search.lfind
+
# setjmp.h entrypoints
libc.src.setjmp.longjmp
libc.src.setjmp.setjmp
diff --git a/libc/config/baremetal/riscv/entrypoints.txt b/libc/config/baremetal/riscv/entrypoints.txt
index 5894b591072ef0..6106ae1b8b234e 100644
--- a/libc/config/baremetal/riscv/entrypoints.txt
+++ b/libc/config/baremetal/riscv/entrypoints.txt
@@ -26,6 +26,9 @@ set(TARGET_LIBC_ENTRYPOINTS
# errno.h entrypoints
libc.src.errno.errno
+ # search.h entrypoints
+ libc.src.search.lfind
+
# string.h entrypoints
libc.src.string.bcmp
libc.src.string.bcopy
diff --git a/libc/config/darwin/arm/entrypoints.txt b/libc/config/darwin/arm/entrypoints.txt
index 2d5dbeff485747..cc730a7849c714 100644
--- a/libc/config/darwin/arm/entrypoints.txt
+++ b/libc/config/darwin/arm/entrypoints.txt
@@ -20,6 +20,9 @@ set(TARGET_LIBC_ENTRYPOINTS
# errno.h entrypoints
libc.src.errno.errno
+ # search.h entrypoints
+ libc.src.search.lfind
+
# string.h entrypoints
libc.src.string.bcmp
libc.src.string.bcopy
diff --git a/libc/config/darwin/x86_64/entrypoints.txt b/libc/config/darwin/x86_64/entrypoints.txt
index 49c19571ac4192..15b099f7890d2f 100644
--- a/libc/config/darwin/x86_64/entrypoints.txt
+++ b/libc/config/darwin/x86_64/entrypoints.txt
@@ -17,6 +17,9 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.ctype.tolower
libc.src.ctype.toupper
+ # search.h entrypoints
+ libc.src.search.lfind
+
# string.h entrypoints
libc.src.string.bcmp
libc.src.string.bzero
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index b3f94a581c8ad9..7ed1386c05b09d 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -942,6 +942,7 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.search.hsearch
libc.src.search.hsearch_r
libc.src.search.insque
+ libc.src.search.lfind
libc.src.search.remque
# threads.h entrypoints
diff --git a/libc/config/linux/arm/entrypoints.txt b/libc/config/linux/arm/entrypoints.txt
index 2ddb7aeefe48ec..f5ae0bbcb12f69 100644
--- a/libc/config/linux/arm/entrypoints.txt
+++ b/libc/config/linux/arm/entrypoints.txt
@@ -20,6 +20,9 @@ set(TARGET_LIBC_ENTRYPOINTS
# errno.h entrypoints
libc.src.errno.errno
+ # search.h entrypoints
+ libc.src.search.lfind
+
# string.h entrypoints
libc.src.string.bcmp
libc.src.string.bcopy
diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index 5c09edf7cfb266..eef4592e27a85f 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -872,6 +872,7 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.search.hsearch
libc.src.search.hsearch_r
libc.src.search.insque
+ libc.src.search.lfind
libc.src.search.remque
# threads.h entrypoints
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index a2fb97d04584d5..ea9e5770fe75c7 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -1005,6 +1005,7 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.search.hsearch
libc.src.search.hsearch_r
libc.src.search.insque
+ libc.src.search.lfind
libc.src.search.remque
# threads.h entrypoints
diff --git a/libc/config/windows/entrypoints.txt b/libc/config/windows/entrypoints.txt
index 8f0b50bcc83ea2..679ef981c90afa 100644
--- a/libc/config/windows/entrypoints.txt
+++ b/libc/config/windows/entrypoints.txt
@@ -17,6 +17,9 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.ctype.tolower
libc.src.ctype.toupper
+ # search.h entrypoints
+ libc.src.search.lfind
+
# string.h entrypoints
libc.src.string.bcmp
libc.src.string.bcopy
diff --git a/libc/docs/libc_search.rst b/libc/docs/libc_search.rst
index 4a7ee288dd43e8..774622d1e66c3f 100644
--- a/libc/docs/libc_search.rst
+++ b/libc/docs/libc_search.rst
@@ -42,7 +42,7 @@ hcreate |check|
hdestroy |check|
hsearch |check|
insque |check|
-lfind
+lfind |check|
lsearch
remque |check|
tdelete
diff --git a/libc/newhdrgen/yaml/search.yaml b/libc/newhdrgen/yaml/search.yaml
index 37d2650bcf0514..af99719c4df958 100644
--- a/libc/newhdrgen/yaml/search.yaml
+++ b/libc/newhdrgen/yaml/search.yaml
@@ -57,3 +57,13 @@ functions:
return_type: void
arguments:
- type: void *
+ - name: lfind
+ standards:
+ - POSIX
+ return_type: void *
+ arguments:
+ - type: void *
+ - type: void *
+ - type: size_t *
+ - type: size_t
+ - type: int(*compar)(const void *, const void *)
diff --git a/libc/spec/posix.td b/libc/spec/posix.td
index beede79a38ec24..ea30b5c42b0e74 100644
--- a/libc/spec/posix.td
+++ b/libc/spec/posix.td
@@ -1618,6 +1618,17 @@ def POSIX : StandardSpec<"POSIX"> {
ArgSpec<VoidPtr>
]
>,
+ FunctionSpec<
+ "lfind",
+ RetValSpec<VoidPtr>,
+ [
+ ArgSpec<VoidPtr>,
+ ArgSpec<VoidPtr>,
+ ArgSpec<SizeTPtr>,
+ ArgSpec<SizeTType>,
+ // TODO: Unsure how to specify int(*compar)(void *, void *)
+ ]
+ >
]
>;
diff --git a/libc/src/search/CMakeLists.txt b/libc/src/search/CMakeLists.txt
index 46ad3e33c02fa9..0490b5939ab0f8 100644
--- a/libc/src/search/CMakeLists.txt
+++ b/libc/src/search/CMakeLists.txt
@@ -98,3 +98,14 @@ add_entrypoint_object(
libc.include.search
libc.src.__support.intrusive_list
)
+
+add_entrypoint_object(
+ lfind
+ SRCS
+ lfind.cpp
+ HDRS
+ lfind.h
+ DEPENDS
+ libc.include.search
+ libc.src.__support.CPP.cstddef
+)
diff --git a/libc/src/search/lfind.cpp b/libc/src/search/lfind.cpp
new file mode 100644
index 00000000000000..debf38de9f1000
--- /dev/null
+++ b/libc/src/search/lfind.cpp
@@ -0,0 +1,29 @@
+//===-- Implementation of lfind -------------------------------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/search/lfind.h"
+#include "src/__support/CPP/cstddef.h" // cpp::byte
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+LLVM_LIBC_FUNCTION(void *, lfind,
+ (void *key, void *base, size_t *nmemb, size_t size,
+ int (*compar)(void *, void *))) {
+ cpp::byte *next = reinterpret_cast<cpp::byte *>(base);
+ cpp::byte *end = next + (*nmemb * size);
+ while (next < end) {
+ if (compar(key, next) == 0) {
+ return next;
+ }
+ next += size;
+ }
+ return nullptr;
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/search/lfind.h b/libc/src/search/lfind.h
new file mode 100644
index 00000000000000..3e0063f8e19f10
--- /dev/null
+++ b/libc/src/search/lfind.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for lfind -------------------------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_SEARCH_LFIND_H
+#define LLVM_LIBC_SRC_SEARCH_LFIND_H
+
+#include "src/__support/macros/config.h"
+#include <search.h> // size_t
+
+namespace LIBC_NAMESPACE_DECL {
+void *lfind(void *key, void *base, size_t *nmemb, size_t size,
+ int (*compar)(void *, void *));
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_SEARCH_LFIND_H
diff --git a/libc/test/src/search/CMakeLists.txt b/libc/test/src/search/CMakeLists.txt
index 8a33edc4293ab2..a1f9aac2094c9b 100644
--- a/libc/test/src/search/CMakeLists.txt
+++ b/libc/test/src/search/CMakeLists.txt
@@ -25,3 +25,13 @@ add_libc_unittest(
libc.src.search.insque
libc.src.search.remque
)
+
+add_libc_unittest(
+ lfind_test
+ SUITE
+ libc_search_unittests
+ SRCS
+ lfind_test.cpp
+ DEPENDS
+ libc.src.search.lfind
+)
diff --git a/libc/test/src/search/lfind_test.cpp b/libc/test/src/search/lfind_test.cpp
new file mode 100644
index 00000000000000..d434194444c330
--- /dev/null
+++ b/libc/test/src/search/lfind_test.cpp
@@ -0,0 +1,46 @@
+//===-- Unittests for lfind -----------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/search/lfind.h"
+#include "test/UnitTest/Test.h"
+
+int compar(void *a, void *b) {
+ return *reinterpret_cast<int *>(a) - *reinterpret_cast<int *>(b);
+}
+
+TEST(LlvmLibcLfindTest, SearchHead) {
+ int list[3] = {1, 2, 3};
+ size_t len = 3;
+ int key = 1;
+ void *ret = LIBC_NAMESPACE::lfind(&key, list, &len, sizeof(int), compar);
+ ASSERT_TRUE(ret == &list[0]);
+}
+
+TEST(LlvmLibcLfindTest, SearchMiddle) {
+ int list[3] = {1, 2, 3};
+ size_t len = 3;
+ int key = 2;
+ void *ret = LIBC_NAMESPACE::lfind(&key, list, &len, sizeof(int), compar);
+ ASSERT_TRUE(ret == &list[1]);
+}
+
+TEST(LlvmLibcLfindTest, SearchTail) {
+ int list[3] = {1, 2, 3};
+ size_t len = 3;
+ int key = 3;
+ void *ret = LIBC_NAMESPACE::lfind(&key, list, &len, sizeof(int), compar);
+ ASSERT_TRUE(ret == &list[2]);
+}
+
+TEST(LlvmLibcLfindTest, SearchNonExistent) {
+ int list[3] = {1, 2, 3};
+ size_t len = 3;
+ int key = 5;
+ void *ret = LIBC_NAMESPACE::lfind(&key, list, &len, sizeof(int), compar);
+ ASSERT_TRUE(ret == nullptr);
+}
>From 5946873c35a8e8e1f2e23de1e9974d40eb370067 Mon Sep 17 00:00:00 2001
From: Duncan <duncpro at icloud.com>
Date: Mon, 4 Nov 2024 15:13:02 -0500
Subject: [PATCH 02/12] replace tabs with spaces
---
libc/config/baremetal/arm/entrypoints.txt | 4 ++--
libc/config/baremetal/riscv/entrypoints.txt | 6 +++---
libc/config/darwin/arm/entrypoints.txt | 4 ++--
libc/config/darwin/x86_64/entrypoints.txt | 4 ++--
libc/config/linux/arm/entrypoints.txt | 4 ++--
libc/config/windows/entrypoints.txt | 4 ++--
6 files changed, 13 insertions(+), 13 deletions(-)
diff --git a/libc/config/baremetal/arm/entrypoints.txt b/libc/config/baremetal/arm/entrypoints.txt
index ae71ea9c327b63..f136711b540966 100644
--- a/libc/config/baremetal/arm/entrypoints.txt
+++ b/libc/config/baremetal/arm/entrypoints.txt
@@ -26,8 +26,8 @@ set(TARGET_LIBC_ENTRYPOINTS
# errno.h entrypoints
libc.src.errno.errno
- # search.h entrypoints
- libc.src.search.lfind
+ # search.h entrypoints
+ libc.src.search.lfind
# setjmp.h entrypoints
libc.src.setjmp.longjmp
diff --git a/libc/config/baremetal/riscv/entrypoints.txt b/libc/config/baremetal/riscv/entrypoints.txt
index 6106ae1b8b234e..08c36ce8396784 100644
--- a/libc/config/baremetal/riscv/entrypoints.txt
+++ b/libc/config/baremetal/riscv/entrypoints.txt
@@ -26,9 +26,9 @@ set(TARGET_LIBC_ENTRYPOINTS
# errno.h entrypoints
libc.src.errno.errno
- # search.h entrypoints
- libc.src.search.lfind
-
+ # search.h entrypoints
+ libc.src.search.lfind
+
# string.h entrypoints
libc.src.string.bcmp
libc.src.string.bcopy
diff --git a/libc/config/darwin/arm/entrypoints.txt b/libc/config/darwin/arm/entrypoints.txt
index cc730a7849c714..13860015ae5841 100644
--- a/libc/config/darwin/arm/entrypoints.txt
+++ b/libc/config/darwin/arm/entrypoints.txt
@@ -20,8 +20,8 @@ set(TARGET_LIBC_ENTRYPOINTS
# errno.h entrypoints
libc.src.errno.errno
- # search.h entrypoints
- libc.src.search.lfind
+ # search.h entrypoints
+ libc.src.search.lfind
# string.h entrypoints
libc.src.string.bcmp
diff --git a/libc/config/darwin/x86_64/entrypoints.txt b/libc/config/darwin/x86_64/entrypoints.txt
index 15b099f7890d2f..64eeed18f3819e 100644
--- a/libc/config/darwin/x86_64/entrypoints.txt
+++ b/libc/config/darwin/x86_64/entrypoints.txt
@@ -17,8 +17,8 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.ctype.tolower
libc.src.ctype.toupper
- # search.h entrypoints
- libc.src.search.lfind
+ # search.h entrypoints
+ libc.src.search.lfind
# string.h entrypoints
libc.src.string.bcmp
diff --git a/libc/config/linux/arm/entrypoints.txt b/libc/config/linux/arm/entrypoints.txt
index f5ae0bbcb12f69..7bdd987a238ee8 100644
--- a/libc/config/linux/arm/entrypoints.txt
+++ b/libc/config/linux/arm/entrypoints.txt
@@ -20,8 +20,8 @@ set(TARGET_LIBC_ENTRYPOINTS
# errno.h entrypoints
libc.src.errno.errno
- # search.h entrypoints
- libc.src.search.lfind
+ # search.h entrypoints
+ libc.src.search.lfind
# string.h entrypoints
libc.src.string.bcmp
diff --git a/libc/config/windows/entrypoints.txt b/libc/config/windows/entrypoints.txt
index 679ef981c90afa..5ffd32373148cd 100644
--- a/libc/config/windows/entrypoints.txt
+++ b/libc/config/windows/entrypoints.txt
@@ -17,8 +17,8 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.ctype.tolower
libc.src.ctype.toupper
- # search.h entrypoints
- libc.src.search.lfind
+ # search.h entrypoints
+ libc.src.search.lfind
# string.h entrypoints
libc.src.string.bcmp
>From 5b4b7ca9afbcaf1e216cd605a54fd41f1fb4108e Mon Sep 17 00:00:00 2001
From: Duncan <duncpro at icloud.com>
Date: Mon, 4 Nov 2024 15:38:25 -0500
Subject: [PATCH 03/12] add const qualifiers to parameters to match the posix
standard
---
libc/newhdrgen/yaml/search.yaml | 4 ++--
libc/src/search/lfind.cpp | 8 ++++----
libc/src/search/lfind.h | 4 ++--
3 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/libc/newhdrgen/yaml/search.yaml b/libc/newhdrgen/yaml/search.yaml
index af99719c4df958..562641e7d2d6dc 100644
--- a/libc/newhdrgen/yaml/search.yaml
+++ b/libc/newhdrgen/yaml/search.yaml
@@ -62,8 +62,8 @@ functions:
- POSIX
return_type: void *
arguments:
- - type: void *
- - type: void *
+ - type: const void *
+ - type: const void *
- type: size_t *
- type: size_t
- type: int(*compar)(const void *, const void *)
diff --git a/libc/src/search/lfind.cpp b/libc/src/search/lfind.cpp
index debf38de9f1000..317f4bf4f6f823 100644
--- a/libc/src/search/lfind.cpp
+++ b/libc/src/search/lfind.cpp
@@ -13,10 +13,10 @@
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(void *, lfind,
- (void *key, void *base, size_t *nmemb, size_t size,
- int (*compar)(void *, void *))) {
- cpp::byte *next = reinterpret_cast<cpp::byte *>(base);
- cpp::byte *end = next + (*nmemb * size);
+ (const void *key, const void *base, size_t *nmemb, size_t size,
+ int (*compar)(const void *, const void *))) {
+ const cpp::byte *next = reinterpret_cast<const cpp::byte *>(base);
+ const cpp::byte *end = next + (*nmemb * size);
while (next < end) {
if (compar(key, next) == 0) {
return next;
diff --git a/libc/src/search/lfind.h b/libc/src/search/lfind.h
index 3e0063f8e19f10..40ac36839dc89d 100644
--- a/libc/src/search/lfind.h
+++ b/libc/src/search/lfind.h
@@ -13,8 +13,8 @@
#include <search.h> // size_t
namespace LIBC_NAMESPACE_DECL {
-void *lfind(void *key, void *base, size_t *nmemb, size_t size,
- int (*compar)(void *, void *));
+void *lfind(const void *key, const void *base, size_t *nmemb, size_t size,
+ int (*compar)(const void *, const void *));
} // namespace LIBC_NAMESPACE_DECL
#endif // LLVM_LIBC_SRC_SEARCH_LFIND_H
>From e1f301948492ced96cc5428ebe91e7c18f791d62 Mon Sep 17 00:00:00 2001
From: Duncan <duncpro at icloud.com>
Date: Mon, 4 Nov 2024 16:16:38 -0500
Subject: [PATCH 04/12] introduce__lsearchcompare_t predicate
---
libc/include/CMakeLists.txt | 1 +
libc/include/llvm-libc-types/CMakeLists.txt | 1 +
libc/include/llvm-libc-types/__lsearchcompare_t.h | 14 ++++++++++++++
libc/newhdrgen/yaml/search.yaml | 3 ++-
libc/spec/posix.td | 5 ++++-
libc/src/search/lfind.cpp | 4 +++-
6 files changed, 25 insertions(+), 3 deletions(-)
create mode 100644 libc/include/llvm-libc-types/__lsearchcompare_t.h
diff --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt
index 5deb5258d532fe..30d0b71d88cc47 100644
--- a/libc/include/CMakeLists.txt
+++ b/libc/include/CMakeLists.txt
@@ -254,6 +254,7 @@ add_header_macro(
.llvm-libc-types.ENTRY
.llvm-libc-types.struct_hsearch_data
.llvm-libc-types.size_t
+ .llvm-libc-types.__lsearchcompare_t
)
add_header_macro(
diff --git a/libc/include/llvm-libc-types/CMakeLists.txt b/libc/include/llvm-libc-types/CMakeLists.txt
index 836e8a507bd6f2..a104ab78689606 100644
--- a/libc/include/llvm-libc-types/CMakeLists.txt
+++ b/libc/include/llvm-libc-types/CMakeLists.txt
@@ -3,6 +3,7 @@ add_header(size_t HDR size_t.h)
add_header(ssize_t HDR ssize_t.h)
add_header(__atfork_callback_t HDR __atfork_callback_t.h)
add_header(__bsearchcompare_t HDR __bsearchcompare_t.h)
+add_header(__lsearchcompare_t HDR __lsearchcompare_t.h)
add_header(__call_once_func_t HDR __call_once_func_t.h)
add_header(__exec_argv_t HDR __exec_argv_t.h)
add_header(__exec_envp_t HDR __exec_envp_t.h)
diff --git a/libc/include/llvm-libc-types/__lsearchcompare_t.h b/libc/include/llvm-libc-types/__lsearchcompare_t.h
new file mode 100644
index 00000000000000..08dc2db274d0c3
--- /dev/null
+++ b/libc/include/llvm-libc-types/__lsearchcompare_t.h
@@ -0,0 +1,14 @@
+//===-- Definition of type __lsearchcompare_t -----------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_TYPES___LSEARCHCOMPARE_T_H
+#define LLVM_LIBC_TYPES___LSEARCHCOMPARE_T_H
+
+typedef int (*__lsearchcompare_t)(const void *, const void *);
+
+#endif // LLVM_LIBC_TYPES___LSEARCHCOMPARE_T_H
diff --git a/libc/newhdrgen/yaml/search.yaml b/libc/newhdrgen/yaml/search.yaml
index 562641e7d2d6dc..a0c73bc679d819 100644
--- a/libc/newhdrgen/yaml/search.yaml
+++ b/libc/newhdrgen/yaml/search.yaml
@@ -4,6 +4,7 @@ types:
- type_name: struct_hsearch_data
- type_name: ENTRY
- type_name: ACTION
+ - type_name: __lsearchcompare_t
enums: []
objects: []
functions:
@@ -66,4 +67,4 @@ functions:
- type: const void *
- type: size_t *
- type: size_t
- - type: int(*compar)(const void *, const void *)
+ - type: __lsearchcompare_t
diff --git a/libc/spec/posix.td b/libc/spec/posix.td
index ea30b5c42b0e74..f350d8a7e7c938 100644
--- a/libc/spec/posix.td
+++ b/libc/spec/posix.td
@@ -100,6 +100,9 @@ def StructStatvfs : NamedType<"struct statvfs">;
def StructStatvfsPtr : PtrType<StructStatvfs>;
def RestrictedStructStatvfsPtr : RestrictedPtrType<StructStatvfs>;
+// The function pointer type for the predicate for lsearch, lfind
+def LSearchCompareT : NamedType<"__lsearchcompare_t">;
+
def POSIX : StandardSpec<"POSIX"> {
PtrType CharPtr = PtrType<CharType>;
RestrictedPtrType RestrictedCharPtr = RestrictedPtrType<CharType>;
@@ -1626,7 +1629,7 @@ def POSIX : StandardSpec<"POSIX"> {
ArgSpec<VoidPtr>,
ArgSpec<SizeTPtr>,
ArgSpec<SizeTType>,
- // TODO: Unsure how to specify int(*compar)(void *, void *)
+ ArgSpec<LSearchCompareT>
]
>
]
diff --git a/libc/src/search/lfind.cpp b/libc/src/search/lfind.cpp
index 317f4bf4f6f823..b1761870c8d22d 100644
--- a/libc/src/search/lfind.cpp
+++ b/libc/src/search/lfind.cpp
@@ -19,7 +19,9 @@ LLVM_LIBC_FUNCTION(void *, lfind,
const cpp::byte *end = next + (*nmemb * size);
while (next < end) {
if (compar(key, next) == 0) {
- return next;
+ // According to IEEE Std 1003.1-2024 we are expected to accept a const reference
+ // to base, but return a non-const reference to the element it contains.
+ return const_cast<cpp::byte *>(next);
}
next += size;
}
>From 3e3da44de8e3d7bf4380853b9447216125cb287e Mon Sep 17 00:00:00 2001
From: Duncan <duncpro at icloud.com>
Date: Mon, 4 Nov 2024 16:28:46 -0500
Subject: [PATCH 05/12] change from subtraction to != in test compar function
---
libc/test/src/search/lfind_test.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/libc/test/src/search/lfind_test.cpp b/libc/test/src/search/lfind_test.cpp
index d434194444c330..00384f7eec14ea 100644
--- a/libc/test/src/search/lfind_test.cpp
+++ b/libc/test/src/search/lfind_test.cpp
@@ -9,8 +9,8 @@
#include "src/search/lfind.h"
#include "test/UnitTest/Test.h"
-int compar(void *a, void *b) {
- return *reinterpret_cast<int *>(a) - *reinterpret_cast<int *>(b);
+int compar(const void *a, const void *b) {
+ return *reinterpret_cast<const int *>(a) != *reinterpret_cast<const int *>(b);
}
TEST(LlvmLibcLfindTest, SearchHead) {
>From d615035d4e88c94bffa12ee7512f32fdd10939ff Mon Sep 17 00:00:00 2001
From: Duncan <duncpro at icloud.com>
Date: Mon, 4 Nov 2024 16:51:17 -0500
Subject: [PATCH 06/12] #include <search.h> -> #include <stddef.h>
---
libc/src/search/lfind.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libc/src/search/lfind.h b/libc/src/search/lfind.h
index 40ac36839dc89d..2eddb027d885a9 100644
--- a/libc/src/search/lfind.h
+++ b/libc/src/search/lfind.h
@@ -10,7 +10,7 @@
#define LLVM_LIBC_SRC_SEARCH_LFIND_H
#include "src/__support/macros/config.h"
-#include <search.h> // size_t
+#include <stddef.h> // size_t
namespace LIBC_NAMESPACE_DECL {
void *lfind(const void *key, const void *base, size_t *nmemb, size_t size,
>From 23d045e50e007a53ba966d0e771c124983150f9f Mon Sep 17 00:00:00 2001
From: Duncan <duncpro at icloud.com>
Date: Mon, 4 Nov 2024 17:04:26 -0500
Subject: [PATCH 07/12] catch overflow when calculating byte_len
---
libc/src/search/CMakeLists.txt | 1 +
libc/src/search/lfind.cpp | 6 +++++-
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/libc/src/search/CMakeLists.txt b/libc/src/search/CMakeLists.txt
index 0490b5939ab0f8..497657f40f2f02 100644
--- a/libc/src/search/CMakeLists.txt
+++ b/libc/src/search/CMakeLists.txt
@@ -108,4 +108,5 @@ add_entrypoint_object(
DEPENDS
libc.include.search
libc.src.__support.CPP.cstddef
+ libc.src.__support.memory_size
)
diff --git a/libc/src/search/lfind.cpp b/libc/src/search/lfind.cpp
index b1761870c8d22d..99a327fe21c4a1 100644
--- a/libc/src/search/lfind.cpp
+++ b/libc/src/search/lfind.cpp
@@ -10,13 +10,17 @@
#include "src/__support/CPP/cstddef.h" // cpp::byte
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
+#include "src/__support/memory_size.h"
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(void *, lfind,
(const void *key, const void *base, size_t *nmemb, size_t size,
int (*compar)(const void *, const void *))) {
+ size_t byte_len = 0;
+ if (internal::mul_overflow(*nmemb, size, &byte_len)) return nullptr;
+
const cpp::byte *next = reinterpret_cast<const cpp::byte *>(base);
- const cpp::byte *end = next + (*nmemb * size);
+ const cpp::byte *end = next + byte_len;
while (next < end) {
if (compar(key, next) == 0) {
// According to IEEE Std 1003.1-2024 we are expected to accept a const reference
>From 7cca8d80a68c2b0aa83eb21a0b7c8716ee09f284 Mon Sep 17 00:00:00 2001
From: Duncan <duncpro at icloud.com>
Date: Mon, 4 Nov 2024 17:10:09 -0500
Subject: [PATCH 08/12] never dereference a nullptr
---
libc/src/search/lfind.cpp | 3 +++
1 file changed, 3 insertions(+)
diff --git a/libc/src/search/lfind.cpp b/libc/src/search/lfind.cpp
index 99a327fe21c4a1..5562df0abd4f67 100644
--- a/libc/src/search/lfind.cpp
+++ b/libc/src/search/lfind.cpp
@@ -16,6 +16,9 @@ namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(void *, lfind,
(const void *key, const void *base, size_t *nmemb, size_t size,
int (*compar)(const void *, const void *))) {
+ if (key == nullptr || base == nullptr || nmemb == nullptr || compar == nullptr)
+ return nullptr;
+
size_t byte_len = 0;
if (internal::mul_overflow(*nmemb, size, &byte_len)) return nullptr;
>From 2f523e9264a7939493c60f6e88e508f7f5bcc0c1 Mon Sep 17 00:00:00 2001
From: Duncan <duncpro at icloud.com>
Date: Mon, 4 Nov 2024 17:12:50 -0500
Subject: [PATCH 09/12] clang-format
---
libc/src/search/lfind.cpp | 19 +++++++++++--------
1 file changed, 11 insertions(+), 8 deletions(-)
diff --git a/libc/src/search/lfind.cpp b/libc/src/search/lfind.cpp
index 5562df0abd4f67..8225e80efd8746 100644
--- a/libc/src/search/lfind.cpp
+++ b/libc/src/search/lfind.cpp
@@ -14,20 +14,23 @@
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(void *, lfind,
- (const void *key, const void *base, size_t *nmemb, size_t size,
- int (*compar)(const void *, const void *))) {
- if (key == nullptr || base == nullptr || nmemb == nullptr || compar == nullptr)
+ (const void *key, const void *base, size_t *nmemb,
+ size_t size, int (*compar)(const void *, const void *))) {
+ if (key == nullptr || base == nullptr || nmemb == nullptr ||
+ compar == nullptr)
return nullptr;
-
+
size_t byte_len = 0;
- if (internal::mul_overflow(*nmemb, size, &byte_len)) return nullptr;
-
+ if (internal::mul_overflow(*nmemb, size, &byte_len))
+ return nullptr;
+
const cpp::byte *next = reinterpret_cast<const cpp::byte *>(base);
const cpp::byte *end = next + byte_len;
while (next < end) {
if (compar(key, next) == 0) {
- // According to IEEE Std 1003.1-2024 we are expected to accept a const reference
- // to base, but return a non-const reference to the element it contains.
+ // According to IEEE Std 1003.1-2024 we are expected to accept a const
+ // reference to base, but return a non-const reference to the element it
+ // contains.
return const_cast<cpp::byte *>(next);
}
next += size;
>From 132692229b2c36f5466e84ede507fcd0f398f73a Mon Sep 17 00:00:00 2001
From: Duncan <duncpro at icloud.com>
Date: Mon, 4 Nov 2024 17:33:42 -0500
Subject: [PATCH 10/12] VoidPtr -> ConstVoidPtr
---
libc/spec/posix.td | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/libc/spec/posix.td b/libc/spec/posix.td
index f350d8a7e7c938..d4712dc0c5d701 100644
--- a/libc/spec/posix.td
+++ b/libc/spec/posix.td
@@ -1625,8 +1625,8 @@ def POSIX : StandardSpec<"POSIX"> {
"lfind",
RetValSpec<VoidPtr>,
[
- ArgSpec<VoidPtr>,
- ArgSpec<VoidPtr>,
+ ArgSpec<ConstVoidPtr>,
+ ArgSpec<ConstVoidPtr>,
ArgSpec<SizeTPtr>,
ArgSpec<SizeTType>,
ArgSpec<LSearchCompareT>
>From 9421214f70b4d0b32248d527ae4fef5f9b268766 Mon Sep 17 00:00:00 2001
From: Duncan <duncpro at icloud.com>
Date: Thu, 7 Nov 2024 13:42:03 -0500
Subject: [PATCH 11/12] replace while loop with for loop
---
libc/src/search/lfind.cpp | 9 ++-------
1 file changed, 2 insertions(+), 7 deletions(-)
diff --git a/libc/src/search/lfind.cpp b/libc/src/search/lfind.cpp
index 8225e80efd8746..08a5cbf94ef392 100644
--- a/libc/src/search/lfind.cpp
+++ b/libc/src/search/lfind.cpp
@@ -26,14 +26,9 @@ LLVM_LIBC_FUNCTION(void *, lfind,
const cpp::byte *next = reinterpret_cast<const cpp::byte *>(base);
const cpp::byte *end = next + byte_len;
- while (next < end) {
- if (compar(key, next) == 0) {
- // According to IEEE Std 1003.1-2024 we are expected to accept a const
- // reference to base, but return a non-const reference to the element it
- // contains.
+ for (; next < end; next += size) {
+ if (compar(key, next) == 0)
return const_cast<cpp::byte *>(next);
- }
- next += size;
}
return nullptr;
}
>From 757e1c9c890ea1784f3a89f1a0b6e5af3ce5c41a Mon Sep 17 00:00:00 2001
From: Duncan <duncpro at icloud.com>
Date: Thu, 7 Nov 2024 14:03:06 -0500
Subject: [PATCH 12/12] Remove unnecessary braces
Co-authored-by: Nick Desaulniers <nickdesaulniers at users.noreply.github.com>
---
libc/src/search/lfind.cpp | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/libc/src/search/lfind.cpp b/libc/src/search/lfind.cpp
index 08a5cbf94ef392..c8bf07de0b9031 100644
--- a/libc/src/search/lfind.cpp
+++ b/libc/src/search/lfind.cpp
@@ -26,10 +26,9 @@ LLVM_LIBC_FUNCTION(void *, lfind,
const cpp::byte *next = reinterpret_cast<const cpp::byte *>(base);
const cpp::byte *end = next + byte_len;
- for (; next < end; next += size) {
+ for (; next < end; next += size)
if (compar(key, next) == 0)
return const_cast<cpp::byte *>(next);
- }
return nullptr;
}
More information about the libc-commits
mailing list