Skip to content

[libc] Implemented wcsrchr #142436

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

Merged
merged 3 commits into from
Jun 2, 2025
Merged

[libc] Implemented wcsrchr #142436

merged 3 commits into from
Jun 2, 2025

Conversation

uzairnawaz
Copy link
Contributor

@uzairnawaz uzairnawaz commented Jun 2, 2025

fixes #124347
Implemented wcsrchr and added tests

@llvmbot llvmbot added the libc label Jun 2, 2025
@llvmbot
Copy link
Member

llvmbot commented Jun 2, 2025

@llvm/pr-subscribers-libc

Author: Uzair Nawaz (uzairnawaz)

Changes

Implemented wcsrchr and added tests


Full diff: https://github.com/llvm/llvm-project/pull/142436.diff

7 Files Affected:

  • (modified) libc/config/linux/x86_64/entrypoints.txt (+1)
  • (modified) libc/include/wchar.yaml (+7)
  • (modified) libc/src/wchar/CMakeLists.txt (+11)
  • (added) libc/src/wchar/wcsrchr.cpp (+31)
  • (added) libc/src/wchar/wcsrchr.h (+21)
  • (modified) libc/test/src/wchar/CMakeLists.txt (+10)
  • (added) libc/test/src/wchar/wcsrchr_test.cpp (+68)
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 545b9227349fe..e6cbfe0257a3e 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -367,6 +367,7 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.wchar.wmemset
     libc.src.wchar.wcschr
     libc.src.wchar.wcspbrk
+    libc.src.wchar.wcsrchr
     libc.src.wchar.wcsspn
     libc.src.wchar.wmemcmp
     libc.src.wchar.wmemcpy
diff --git a/libc/include/wchar.yaml b/libc/include/wchar.yaml
index bfd9a10342019..39732feb62fcd 100644
--- a/libc/include/wchar.yaml
+++ b/libc/include/wchar.yaml
@@ -49,6 +49,13 @@ functions:
     arguments:
       - type: const wchar_t *
       - type: const wchar_t *
+  - name: wcsrchr
+    standards:
+      - stdc
+    return_type: const wchar_t *
+    arguments:
+      - type: const wchar_t *
+      - type: wchar_t
   - name: wcsspn
     standards:
       - stdc
diff --git a/libc/src/wchar/CMakeLists.txt b/libc/src/wchar/CMakeLists.txt
index 9db121762348b..dd597550e06d8 100644
--- a/libc/src/wchar/CMakeLists.txt
+++ b/libc/src/wchar/CMakeLists.txt
@@ -68,6 +68,17 @@ add_entrypoint_object(
     libc.src.__support.wctype_utils
 )
 
+add_entrypoint_object(
+  wcsrchr
+  SRCS
+    wcsrchr.cpp
+  HDRS
+    wcsrchr.h
+  DEPENDS
+    libc.hdr.wchar_macros
+    libc.src.__support.wctype_utils
+)
+
 add_entrypoint_object(
   wcsspn
   SRCS
diff --git a/libc/src/wchar/wcsrchr.cpp b/libc/src/wchar/wcsrchr.cpp
new file mode 100644
index 0000000000000..bb4e373bb1ce1
--- /dev/null
+++ b/libc/src/wchar/wcsrchr.cpp
@@ -0,0 +1,31 @@
+//===-- Implementation of wcsrchr -----------------------------------------===//
+//
+// 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/wchar/wcsrchr.h"
+
+#include "hdr/types/wchar_t.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/null_check.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(const wchar_t *, wcsrchr, (const wchar_t *s, wchar_t c)) {
+  LIBC_CRASH_ON_NULLPTR(s);
+
+  const wchar_t *last_occurrence = nullptr;
+  while (true) {
+    if (*s == c)
+      last_occurrence = s;
+    if (*s == L'\0')
+      return last_occurrence;
+    ++s;
+  }
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/wchar/wcsrchr.h b/libc/src/wchar/wcsrchr.h
new file mode 100644
index 0000000000000..5e9d8c3c2db92
--- /dev/null
+++ b/libc/src/wchar/wcsrchr.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for wcsrchr ---------------------------------===//
+//
+// 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_WCHAR_WCSRCHR_H
+#define LLVM_LIBC_SRC_WCHAR_WCSRCHR_H
+
+#include "hdr/types/wchar_t.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+const wchar_t *wcsrchr(const wchar_t *s, wchar_t c);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_WCHAR_WCSRCHR_H
diff --git a/libc/test/src/wchar/CMakeLists.txt b/libc/test/src/wchar/CMakeLists.txt
index 9bc230e0bddf3..6a212a620f853 100644
--- a/libc/test/src/wchar/CMakeLists.txt
+++ b/libc/test/src/wchar/CMakeLists.txt
@@ -65,6 +65,16 @@ add_libc_test(
     libc.src.wchar.wcspbrk
 )
 
+add_libc_test(
+  wcsrchr_test
+  SUITE
+    libc_wchar_unittests
+  SRCS
+    wcsrchr_test.cpp
+  DEPENDS
+    libc.src.wchar.wcsrchr
+)
+
 add_libc_test(
   wcsspn_test
   SUITE
diff --git a/libc/test/src/wchar/wcsrchr_test.cpp b/libc/test/src/wchar/wcsrchr_test.cpp
new file mode 100644
index 0000000000000..707dfb6756ee9
--- /dev/null
+++ b/libc/test/src/wchar/wcsrchr_test.cpp
@@ -0,0 +1,68 @@
+//===-- Unittests for wcsrchr ---------------------------------------------===//
+//
+// 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 "hdr/types/wchar_t.h"
+#include "src/wchar/wcsrchr.h"
+#include "test/UnitTest/Test.h"
+
+TEST(LlvmLibcWCSRChrTest, FindsFirstCharacter) {
+  // Should return pointer to original string since 'a' is the first character.
+  const wchar_t *src = L"abcde";
+  ASSERT_EQ(LIBC_NAMESPACE::wcsrchr(src, L'a'), src);
+}
+
+TEST(LlvmLibcWCSRChrTest, FindsMiddleCharacter) {
+  // Should return pointer to 'c'.
+  const wchar_t *src = L"abcde";
+  ASSERT_EQ(LIBC_NAMESPACE::wcsrchr(src, L'c'), (src + 2));
+}
+
+TEST(LlvmLibcWCSRChrTest, FindsLastCharacterThatIsNotNullTerminator) {
+  // Should return pointer to 'e'.
+  const wchar_t *src = L"abcde";
+  ASSERT_EQ(LIBC_NAMESPACE::wcsrchr(src, L'e'), (src + 4));
+}
+
+TEST(LlvmLibcWCSRChrTest, FindsNullTerminator) {
+  // Should return pointer to null terminator.
+  const wchar_t *src = L"abcde";
+  ASSERT_EQ(LIBC_NAMESPACE::wcsrchr(src, L'\0'), (src + 5));
+}
+
+TEST(LlvmLibcWCSRChrTest, CharacterNotWithinStringShouldReturnNullptr) {
+  // Since 'z' is not within the string, should return nullptr.
+  const wchar_t *src = L"abcde";
+  ASSERT_EQ(LIBC_NAMESPACE::wcsrchr(src, L'z'), nullptr);
+}
+
+TEST(LlvmLibcWCSRChrTest, ShouldFindLastOfDuplicates) {
+  // Should return pointer to the last '1'.
+  const wchar_t *src = L"abc1def1ghi";
+  ASSERT_EQ((int)(LIBC_NAMESPACE::wcsrchr(src, L'1') - src), 7);
+
+  // Should return pointer to the last 'X'
+  const wchar_t *dups = L"XXXXX";
+  ASSERT_EQ(LIBC_NAMESPACE::wcsrchr(dups, L'X'), dups + 4);
+}
+
+TEST(LlvmLibcWCSRChrTest, EmptyStringShouldOnlyMatchNullTerminator) {
+  // Null terminator should match
+  const wchar_t *src = L"";
+  ASSERT_EQ(src, LIBC_NAMESPACE::wcsrchr(src, L'\0'));
+  // All other characters should not match
+  ASSERT_EQ(LIBC_NAMESPACE::wcsrchr(src, L'Z'), nullptr);
+  ASSERT_EQ(LIBC_NAMESPACE::wcsrchr(src, L'3'), nullptr);
+  ASSERT_EQ(LIBC_NAMESPACE::wcsrchr(src, L'*'), nullptr);
+}
+
+#if defined(LIBC_ADD_NULL_CHECKS) && !defined(LIBC_HAS_SANITIZER)
+TEST(LlvmLibcWCSRChrTest, NullptrCrash) {
+  // Passing in a nullptr should crash the program.
+  EXPECT_DEATH([] { LIBC_NAMESPACE::wcsrchr(nullptr, L'a'); }, WITH_SIGNAL(-1));
+}
+#endif // LIBC_HAS_ADDRESS_SANITIZER

Copy link
Contributor

@michaelrj-google michaelrj-google left a comment

Choose a reason for hiding this comment

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

just a build fix, otherwise LGTM

wcsrchr.h
DEPENDS
libc.hdr.wchar_macros
libc.src.__support.wctype_utils
Copy link
Contributor

Choose a reason for hiding this comment

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

don't need wctype_utils

@michaelrj-google
Copy link
Contributor

please add "fixes #124347" to the description

@michaelrj-google michaelrj-google merged commit dabe983 into llvm:main Jun 2, 2025
14 of 15 checks passed
sallto pushed a commit to sallto/llvm-project that referenced this pull request Jun 3, 2025
fixes llvm#124347 
Implemented wcsrchr and added tests
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[libc][wchar] implement wcsrchr
3 participants