[libc-commits] [libc] [libc] Add bindtextdomain and bind_textdomain_codeset stubs (PR #232711)

Jeff Bailey via libc-commits libc-commits at lists.llvm.org
Fri Oct 16 05:12:24 PDT 2026


https://github.com/kaladron created https://github.com/llvm/llvm-project/pull/232711

Added stateless stubs for bindtextdomain and bind_textdomain_codeset behind LLVM_LIBC_ENABLE_EXPERIMENTAL_ENTRYPOINTS.  Both functions return nullptr without modifying errno when given a null or empty domain name, and return "/usr/share/locale" (for bindtextdomain) or nullptr (for bind_textdomain_codeset) when queried with a null setting argument.

Assisted-by: Automated tooling, human reviewed.

>From 50ac145d5b94f23104b3da4183a30121d1037258 Mon Sep 17 00:00:00 2001
From: Jeff Bailey <jbailey at raspberryginger.com>
Date: Thu, 15 Oct 2026 15:12:05 +0100
Subject: [PATCH] [libc] Add bindtextdomain and bind_textdomain_codeset stubs

Added stateless stubs for bindtextdomain and bind_textdomain_codeset
behind LLVM_LIBC_ENABLE_EXPERIMENTAL_ENTRYPOINTS.  Both functions return
nullptr without modifying errno when given a null or empty domain name,
and return "/usr/share/locale" (for bindtextdomain) or nullptr (for
bind_textdomain_codeset) when queried with a null setting argument.

Assisted-by: Automated tooling, human reviewed.
---
 libc/config/baremetal/aarch64/entrypoints.txt |  2 ++
 libc/config/baremetal/arm/entrypoints.txt     |  2 ++
 libc/config/baremetal/hexagon/entrypoints.txt |  2 ++
 libc/config/baremetal/riscv/entrypoints.txt   |  2 ++
 libc/config/linux/aarch64/entrypoints.txt     |  2 ++
 libc/config/linux/arm/entrypoints.txt         |  2 ++
 libc/config/linux/riscv/entrypoints.txt       |  2 ++
 libc/config/linux/x86_64/entrypoints.txt      |  2 ++
 libc/include/libintl.yaml                     | 14 ++++++++
 libc/src/libintl/CMakeLists.txt               | 16 ++++++++++
 libc/src/libintl/bind_textdomain_codeset.cpp  | 30 +++++++++++++++++
 libc/src/libintl/bind_textdomain_codeset.h    | 25 +++++++++++++++
 libc/src/libintl/bindtextdomain.cpp           | 32 +++++++++++++++++++
 libc/src/libintl/bindtextdomain.h             | 25 +++++++++++++++
 libc/test/src/libintl/CMakeLists.txt          |  2 ++
 libc/test/src/libintl/libintl_test.cpp        | 28 ++++++++++++++++
 16 files changed, 188 insertions(+)
 create mode 100644 libc/src/libintl/bind_textdomain_codeset.cpp
 create mode 100644 libc/src/libintl/bind_textdomain_codeset.h
 create mode 100644 libc/src/libintl/bindtextdomain.cpp
 create mode 100644 libc/src/libintl/bindtextdomain.h

diff --git a/libc/config/baremetal/aarch64/entrypoints.txt b/libc/config/baremetal/aarch64/entrypoints.txt
index a85fa19a92fcc..061b923d1ffbf 100644
--- a/libc/config/baremetal/aarch64/entrypoints.txt
+++ b/libc/config/baremetal/aarch64/entrypoints.txt
@@ -969,6 +969,8 @@ endif()
 if(LLVM_LIBC_ENABLE_EXPERIMENTAL_ENTRYPOINTS)
   list(APPEND TARGET_LIBC_ENTRYPOINTS
     # libintl.h entrypoints
+    libc.src.libintl.bind_textdomain_codeset
+    libc.src.libintl.bindtextdomain
     libc.src.libintl.textdomain
 
     # regex.h entrypoints
diff --git a/libc/config/baremetal/arm/entrypoints.txt b/libc/config/baremetal/arm/entrypoints.txt
index 87fdcd0465230..7d1d061b1f2d7 100644
--- a/libc/config/baremetal/arm/entrypoints.txt
+++ b/libc/config/baremetal/arm/entrypoints.txt
@@ -1004,6 +1004,8 @@ endif()
 if(LLVM_LIBC_ENABLE_EXPERIMENTAL_ENTRYPOINTS)
   list(APPEND TARGET_LIBC_ENTRYPOINTS
     # libintl.h entrypoints
+    libc.src.libintl.bind_textdomain_codeset
+    libc.src.libintl.bindtextdomain
     libc.src.libintl.textdomain
 
     # regex.h entrypoints
diff --git a/libc/config/baremetal/hexagon/entrypoints.txt b/libc/config/baremetal/hexagon/entrypoints.txt
index cfee5f8240e60..3290e646c177f 100644
--- a/libc/config/baremetal/hexagon/entrypoints.txt
+++ b/libc/config/baremetal/hexagon/entrypoints.txt
@@ -985,6 +985,8 @@ endif()
 if(LLVM_LIBC_ENABLE_EXPERIMENTAL_ENTRYPOINTS)
   list(APPEND TARGET_LIBC_ENTRYPOINTS
     # libintl.h entrypoints
+    libc.src.libintl.bind_textdomain_codeset
+    libc.src.libintl.bindtextdomain
     libc.src.libintl.textdomain
 
     # regex.h entrypoints
diff --git a/libc/config/baremetal/riscv/entrypoints.txt b/libc/config/baremetal/riscv/entrypoints.txt
index 19397087f3e92..de4602de33a5d 100644
--- a/libc/config/baremetal/riscv/entrypoints.txt
+++ b/libc/config/baremetal/riscv/entrypoints.txt
@@ -996,6 +996,8 @@ endif()
 if(LLVM_LIBC_ENABLE_EXPERIMENTAL_ENTRYPOINTS)
   list(APPEND TARGET_LIBC_ENTRYPOINTS
     # libintl.h entrypoints
+    libc.src.libintl.bind_textdomain_codeset
+    libc.src.libintl.bindtextdomain
     libc.src.libintl.textdomain
 
     # regex.h entrypoints
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index b2c8d62a65f4e..761b4e1055705 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -1497,6 +1497,8 @@ if(LLVM_LIBC_ENABLE_EXPERIMENTAL_ENTRYPOINTS)
       libc.src.glob.globfree
 
       # libintl.h entrypoints
+      libc.src.libintl.bind_textdomain_codeset
+      libc.src.libintl.bindtextdomain
       libc.src.libintl.textdomain
 
       # net/if.h entrypoints
diff --git a/libc/config/linux/arm/entrypoints.txt b/libc/config/linux/arm/entrypoints.txt
index 023d298170c24..8166470d222f5 100644
--- a/libc/config/linux/arm/entrypoints.txt
+++ b/libc/config/linux/arm/entrypoints.txt
@@ -725,6 +725,8 @@ if(LLVM_LIBC_ENABLE_EXPERIMENTAL_ENTRYPOINTS)
   if(LLVM_LIBC_FULL_BUILD)
     list(APPEND TARGET_LIBC_ENTRYPOINTS
       # libintl.h entrypoints
+      libc.src.libintl.bind_textdomain_codeset
+      libc.src.libintl.bindtextdomain
       libc.src.libintl.textdomain
 
       # regex.h entrypoints
diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index 3bdc686c0e4ce..ce89db9476606 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -1709,6 +1709,8 @@ if(LLVM_LIBC_ENABLE_EXPERIMENTAL_ENTRYPOINTS)
       libc.src.glob.globfree
 
       # libintl.h entrypoints
+      libc.src.libintl.bind_textdomain_codeset
+      libc.src.libintl.bindtextdomain
       libc.src.libintl.textdomain
 
       # net/if.h entrypoints
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 23a588f65d743..88659ca320d31 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -1735,6 +1735,8 @@ if(LLVM_LIBC_ENABLE_EXPERIMENTAL_ENTRYPOINTS)
       libc.src.glob.globfree
 
       # libintl.h entrypoints
+      libc.src.libintl.bind_textdomain_codeset
+      libc.src.libintl.bindtextdomain
       libc.src.libintl.textdomain
 
       # net/if.h entrypoints
diff --git a/libc/include/libintl.yaml b/libc/include/libintl.yaml
index 7e429f3a6b7b2..3ef6e02eb77a7 100644
--- a/libc/include/libintl.yaml
+++ b/libc/include/libintl.yaml
@@ -7,6 +7,20 @@ types:
 enums: []
 objects: []
 functions:
+  - name: bind_textdomain_codeset
+    standards:
+      - posix
+    return_type: char *
+    arguments:
+      - type: const char *
+      - type: const char *
+  - name: bindtextdomain
+    standards:
+      - posix
+    return_type: char *
+    arguments:
+      - type: const char *
+      - type: const char *
   - name: textdomain
     standards:
       - posix
diff --git a/libc/src/libintl/CMakeLists.txt b/libc/src/libintl/CMakeLists.txt
index 063f12227a4b7..9b506e2b99e0e 100644
--- a/libc/src/libintl/CMakeLists.txt
+++ b/libc/src/libintl/CMakeLists.txt
@@ -1,3 +1,19 @@
+add_entrypoint_object(
+  bind_textdomain_codeset
+  SRCS
+    bind_textdomain_codeset.cpp
+  HDRS
+    bind_textdomain_codeset.h
+)
+
+add_entrypoint_object(
+  bindtextdomain
+  SRCS
+    bindtextdomain.cpp
+  HDRS
+    bindtextdomain.h
+)
+
 add_entrypoint_object(
   textdomain
   SRCS
diff --git a/libc/src/libintl/bind_textdomain_codeset.cpp b/libc/src/libintl/bind_textdomain_codeset.cpp
new file mode 100644
index 0000000000000..83b7b56c1dae5
--- /dev/null
+++ b/libc/src/libintl/bind_textdomain_codeset.cpp
@@ -0,0 +1,30 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Implementation of bind_textdomain_codeset (stub).
+///
+//===----------------------------------------------------------------------===//
+
+#include "src/libintl/bind_textdomain_codeset.h"
+
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(char *, bind_textdomain_codeset,
+                   (const char *domainname, const char *codeset)) {
+  // TODO: Implement message catalogs. For now, validate domainname and return
+  // the requested codeset (or nullptr when querying).
+  if (domainname == nullptr || domainname[0] == '\0' || codeset == nullptr)
+    return nullptr;
+  return const_cast<char *>(codeset);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/libintl/bind_textdomain_codeset.h b/libc/src/libintl/bind_textdomain_codeset.h
new file mode 100644
index 0000000000000..fa70742637185
--- /dev/null
+++ b/libc/src/libintl/bind_textdomain_codeset.h
@@ -0,0 +1,25 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Implementation header for bind_textdomain_codeset.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_LIBINTL_BIND_TEXTDOMAIN_CODESET_H
+#define LLVM_LIBC_SRC_LIBINTL_BIND_TEXTDOMAIN_CODESET_H
+
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+char *bind_textdomain_codeset(const char *domainname, const char *codeset);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_LIBINTL_BIND_TEXTDOMAIN_CODESET_H
diff --git a/libc/src/libintl/bindtextdomain.cpp b/libc/src/libintl/bindtextdomain.cpp
new file mode 100644
index 0000000000000..a6b6e0ce3fd50
--- /dev/null
+++ b/libc/src/libintl/bindtextdomain.cpp
@@ -0,0 +1,32 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Implementation of bindtextdomain (stub).
+///
+//===----------------------------------------------------------------------===//
+
+#include "src/libintl/bindtextdomain.h"
+
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(char *, bindtextdomain,
+                   (const char *domainname, const char *dirname)) {
+  // TODO: Implement message catalogs. For now, validate domainname and return
+  // the default locale directory when querying or dirname when setting.
+  if (domainname == nullptr || domainname[0] == '\0')
+    return nullptr;
+  if (dirname == nullptr)
+    return const_cast<char *>("/usr/share/locale");
+  return const_cast<char *>(dirname);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/libintl/bindtextdomain.h b/libc/src/libintl/bindtextdomain.h
new file mode 100644
index 0000000000000..dfa99bfe163e3
--- /dev/null
+++ b/libc/src/libintl/bindtextdomain.h
@@ -0,0 +1,25 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Implementation header for bindtextdomain.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_LIBINTL_BINDTEXTDOMAIN_H
+#define LLVM_LIBC_SRC_LIBINTL_BINDTEXTDOMAIN_H
+
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+char *bindtextdomain(const char *domainname, const char *dirname);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_LIBINTL_BINDTEXTDOMAIN_H
diff --git a/libc/test/src/libintl/CMakeLists.txt b/libc/test/src/libintl/CMakeLists.txt
index 955c5214b53eb..ecc2e0901c19d 100644
--- a/libc/test/src/libintl/CMakeLists.txt
+++ b/libc/test/src/libintl/CMakeLists.txt
@@ -8,6 +8,8 @@ if(LLVM_LIBC_FULL_BUILD AND LLVM_LIBC_ENABLE_EXPERIMENTAL_ENTRYPOINTS)
     SRCS
       libintl_test.cpp
     DEPENDS
+      libc.src.libintl.bind_textdomain_codeset
+      libc.src.libintl.bindtextdomain
       libc.src.libintl.textdomain
       libc.test.UnitTest.ErrnoCheckingTest
       libc.test.UnitTest.ErrnoSetterMatcher
diff --git a/libc/test/src/libintl/libintl_test.cpp b/libc/test/src/libintl/libintl_test.cpp
index 9f31d16b87bcb..2ce3ec41dbfab 100644
--- a/libc/test/src/libintl/libintl_test.cpp
+++ b/libc/test/src/libintl/libintl_test.cpp
@@ -11,6 +11,8 @@
 ///
 //===----------------------------------------------------------------------===//
 
+#include "src/libintl/bind_textdomain_codeset.h"
+#include "src/libintl/bindtextdomain.h"
 #include "src/libintl/textdomain.h"
 #include "test/UnitTest/ErrnoCheckingTest.h"
 #include "test/UnitTest/ErrnoSetterMatcher.h"
@@ -27,3 +29,29 @@ TEST_F(LlvmLibcLibintlTest, Textdomain) {
   EXPECT_THAT(LIBC_NAMESPACE::textdomain(DOMAIN_NAME),
               Succeeds(const_cast<char *>(DOMAIN_NAME)));
 }
+
+TEST_F(LlvmLibcLibintlTest, Bindtextdomain) {
+  EXPECT_THAT(LIBC_NAMESPACE::bindtextdomain(nullptr, "/custom/dir"),
+              Succeeds<char *>(nullptr));
+  EXPECT_THAT(LIBC_NAMESPACE::bindtextdomain("", "/custom/dir"),
+              Succeeds<char *>(nullptr));
+  EXPECT_STREQ(LIBC_NAMESPACE::bindtextdomain("my_app", nullptr),
+               "/usr/share/locale");
+
+  constexpr const char *DIR_NAME = "/custom/dir";
+  EXPECT_THAT(LIBC_NAMESPACE::bindtextdomain("my_app", DIR_NAME),
+              Succeeds(const_cast<char *>(DIR_NAME)));
+}
+
+TEST_F(LlvmLibcLibintlTest, BindTextdomainCodeset) {
+  EXPECT_THAT(LIBC_NAMESPACE::bind_textdomain_codeset(nullptr, "UTF-8"),
+              Succeeds<char *>(nullptr));
+  EXPECT_THAT(LIBC_NAMESPACE::bind_textdomain_codeset("", "UTF-8"),
+              Succeeds<char *>(nullptr));
+  EXPECT_THAT(LIBC_NAMESPACE::bind_textdomain_codeset("my_app", nullptr),
+              Succeeds<char *>(nullptr));
+
+  constexpr const char *CODESET = "UTF-8";
+  EXPECT_THAT(LIBC_NAMESPACE::bind_textdomain_codeset("my_app", CODESET),
+              Succeeds(const_cast<char *>(CODESET)));
+}



More information about the libc-commits mailing list