[libc-commits] [libc] 636c61e - [libc] Add <libintl.h> and textdomain stub (#232351)
via libc-commits
libc-commits at lists.llvm.org
Thu Oct 15 23:13:16 PDT 2026
Author: Jeff Bailey
Date: 2026-10-16T07:13:08+01:00
New Revision: 636c61e9565b7d83368874dacc8c538481dbe9e1
URL: https://github.com/llvm/llvm-project/commit/636c61e9565b7d83368874dacc8c538481dbe9e1
DIFF: https://github.com/llvm/llvm-project/commit/636c61e9565b7d83368874dacc8c538481dbe9e1.diff
LOG: [libc] Add <libintl.h> and textdomain stub (#232351)
POSIX.1-2024 standardises the <libintl.h> message translation
interfaces. Because LLVM-libc currently supports only the "C" locale,
message catalog functions can be satisfied with stateless stubs that do
not access the filesystem.
Added the <libintl.h> header generation specification and the textdomain
entrypoint behind LLVM_LIBC_ENABLE_EXPERIMENTAL_ENTRYPOINTS, returning
"messages" when querying or resetting the domain and returning the input
domain name otherwise.
Assisted-by: Automated tooling, human reviewed.
Added:
libc/include/libintl.yaml
libc/src/libintl/CMakeLists.txt
libc/src/libintl/textdomain.cpp
libc/src/libintl/textdomain.h
libc/test/src/libintl/CMakeLists.txt
libc/test/src/libintl/libintl_test.cpp
Modified:
libc/config/baremetal/aarch64/entrypoints.txt
libc/config/baremetal/aarch64/headers.txt
libc/config/baremetal/arm/entrypoints.txt
libc/config/baremetal/arm/headers.txt
libc/config/baremetal/hexagon/entrypoints.txt
libc/config/baremetal/hexagon/headers.txt
libc/config/baremetal/riscv/entrypoints.txt
libc/config/baremetal/riscv/headers.txt
libc/config/linux/aarch64/entrypoints.txt
libc/config/linux/aarch64/headers.txt
libc/config/linux/arm/entrypoints.txt
libc/config/linux/arm/headers.txt
libc/config/linux/riscv/entrypoints.txt
libc/config/linux/riscv/headers.txt
libc/config/linux/x86_64/entrypoints.txt
libc/config/linux/x86_64/headers.txt
libc/include/CMakeLists.txt
libc/src/CMakeLists.txt
libc/test/src/CMakeLists.txt
Removed:
################################################################################
diff --git a/libc/config/baremetal/aarch64/entrypoints.txt b/libc/config/baremetal/aarch64/entrypoints.txt
index cb341c2d8b0e30..a85fa19a92fccf 100644
--- a/libc/config/baremetal/aarch64/entrypoints.txt
+++ b/libc/config/baremetal/aarch64/entrypoints.txt
@@ -968,6 +968,9 @@ endif()
if(LLVM_LIBC_ENABLE_EXPERIMENTAL_ENTRYPOINTS)
list(APPEND TARGET_LIBC_ENTRYPOINTS
+ # libintl.h entrypoints
+ libc.src.libintl.textdomain
+
# regex.h entrypoints
libc.src.regex.regcomp
libc.src.regex.regexec
diff --git a/libc/config/baremetal/aarch64/headers.txt b/libc/config/baremetal/aarch64/headers.txt
index 42dcd87b680d65..b5ccf3c437a37c 100644
--- a/libc/config/baremetal/aarch64/headers.txt
+++ b/libc/config/baremetal/aarch64/headers.txt
@@ -27,5 +27,8 @@ set(TARGET_PUBLIC_HEADERS
)
if(LLVM_LIBC_ENABLE_EXPERIMENTAL_ENTRYPOINTS)
- list(APPEND TARGET_PUBLIC_HEADERS libc.include.regex)
+ list(APPEND TARGET_PUBLIC_HEADERS
+ libc.include.libintl
+ libc.include.regex
+ )
endif()
diff --git a/libc/config/baremetal/arm/entrypoints.txt b/libc/config/baremetal/arm/entrypoints.txt
index 65e36c110d696f..87fdcd04652303 100644
--- a/libc/config/baremetal/arm/entrypoints.txt
+++ b/libc/config/baremetal/arm/entrypoints.txt
@@ -1003,6 +1003,9 @@ endif()
if(LLVM_LIBC_ENABLE_EXPERIMENTAL_ENTRYPOINTS)
list(APPEND TARGET_LIBC_ENTRYPOINTS
+ # libintl.h entrypoints
+ libc.src.libintl.textdomain
+
# regex.h entrypoints
libc.src.regex.regcomp
libc.src.regex.regexec
diff --git a/libc/config/baremetal/arm/headers.txt b/libc/config/baremetal/arm/headers.txt
index a69660a97fdae1..9740d65762e64d 100644
--- a/libc/config/baremetal/arm/headers.txt
+++ b/libc/config/baremetal/arm/headers.txt
@@ -28,5 +28,8 @@ set(TARGET_PUBLIC_HEADERS
)
if(LLVM_LIBC_ENABLE_EXPERIMENTAL_ENTRYPOINTS)
- list(APPEND TARGET_PUBLIC_HEADERS libc.include.regex)
+ list(APPEND TARGET_PUBLIC_HEADERS
+ libc.include.libintl
+ libc.include.regex
+ )
endif()
diff --git a/libc/config/baremetal/hexagon/entrypoints.txt b/libc/config/baremetal/hexagon/entrypoints.txt
index c6244a2f4d728c..cfee5f8240e60c 100644
--- a/libc/config/baremetal/hexagon/entrypoints.txt
+++ b/libc/config/baremetal/hexagon/entrypoints.txt
@@ -984,6 +984,9 @@ endif()
if(LLVM_LIBC_ENABLE_EXPERIMENTAL_ENTRYPOINTS)
list(APPEND TARGET_LIBC_ENTRYPOINTS
+ # libintl.h entrypoints
+ libc.src.libintl.textdomain
+
# regex.h entrypoints
libc.src.regex.regcomp
libc.src.regex.regexec
diff --git a/libc/config/baremetal/hexagon/headers.txt b/libc/config/baremetal/hexagon/headers.txt
index a69660a97fdae1..9740d65762e64d 100644
--- a/libc/config/baremetal/hexagon/headers.txt
+++ b/libc/config/baremetal/hexagon/headers.txt
@@ -28,5 +28,8 @@ set(TARGET_PUBLIC_HEADERS
)
if(LLVM_LIBC_ENABLE_EXPERIMENTAL_ENTRYPOINTS)
- list(APPEND TARGET_PUBLIC_HEADERS libc.include.regex)
+ list(APPEND TARGET_PUBLIC_HEADERS
+ libc.include.libintl
+ libc.include.regex
+ )
endif()
diff --git a/libc/config/baremetal/riscv/entrypoints.txt b/libc/config/baremetal/riscv/entrypoints.txt
index caa5f3c559cc6c..19397087f3e92c 100644
--- a/libc/config/baremetal/riscv/entrypoints.txt
+++ b/libc/config/baremetal/riscv/entrypoints.txt
@@ -995,6 +995,9 @@ endif()
if(LLVM_LIBC_ENABLE_EXPERIMENTAL_ENTRYPOINTS)
list(APPEND TARGET_LIBC_ENTRYPOINTS
+ # libintl.h entrypoints
+ libc.src.libintl.textdomain
+
# regex.h entrypoints
libc.src.regex.regcomp
libc.src.regex.regexec
diff --git a/libc/config/baremetal/riscv/headers.txt b/libc/config/baremetal/riscv/headers.txt
index a69660a97fdae1..9740d65762e64d 100644
--- a/libc/config/baremetal/riscv/headers.txt
+++ b/libc/config/baremetal/riscv/headers.txt
@@ -28,5 +28,8 @@ set(TARGET_PUBLIC_HEADERS
)
if(LLVM_LIBC_ENABLE_EXPERIMENTAL_ENTRYPOINTS)
- list(APPEND TARGET_PUBLIC_HEADERS libc.include.regex)
+ list(APPEND TARGET_PUBLIC_HEADERS
+ libc.include.libintl
+ libc.include.regex
+ )
endif()
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 42ce377d7dca9a..b2c8d62a65f4e1 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -1496,6 +1496,9 @@ if(LLVM_LIBC_ENABLE_EXPERIMENTAL_ENTRYPOINTS)
libc.src.glob.glob
libc.src.glob.globfree
+ # libintl.h entrypoints
+ libc.src.libintl.textdomain
+
# net/if.h entrypoints
libc.src.net.if_freenameindex
libc.src.net.if_nameindex
diff --git a/libc/config/linux/aarch64/headers.txt b/libc/config/linux/aarch64/headers.txt
index 5a2083c8f39d39..3e96e6637da940 100644
--- a/libc/config/linux/aarch64/headers.txt
+++ b/libc/config/linux/aarch64/headers.txt
@@ -98,6 +98,7 @@ set(TARGET_PUBLIC_HEADERS
if(LLVM_LIBC_FULL_BUILD AND LLVM_LIBC_ENABLE_EXPERIMENTAL_ENTRYPOINTS)
list(APPEND TARGET_PUBLIC_HEADERS
libc.include.glob
+ libc.include.libintl
libc.include.netdb
libc.include.regex
libc.include.sys_ptrace
diff --git a/libc/config/linux/arm/entrypoints.txt b/libc/config/linux/arm/entrypoints.txt
index 85af57dc2c8d23..023d298170c245 100644
--- a/libc/config/linux/arm/entrypoints.txt
+++ b/libc/config/linux/arm/entrypoints.txt
@@ -724,6 +724,9 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
if(LLVM_LIBC_ENABLE_EXPERIMENTAL_ENTRYPOINTS)
if(LLVM_LIBC_FULL_BUILD)
list(APPEND TARGET_LIBC_ENTRYPOINTS
+ # libintl.h entrypoints
+ libc.src.libintl.textdomain
+
# regex.h entrypoints
libc.src.regex.regcomp
libc.src.regex.regexec
diff --git a/libc/config/linux/arm/headers.txt b/libc/config/linux/arm/headers.txt
index a46840383142ae..6ccc9c476199d3 100644
--- a/libc/config/linux/arm/headers.txt
+++ b/libc/config/linux/arm/headers.txt
@@ -38,6 +38,7 @@ set(TARGET_PUBLIC_HEADERS
if(LLVM_LIBC_FULL_BUILD AND LLVM_LIBC_ENABLE_EXPERIMENTAL_ENTRYPOINTS)
list(APPEND TARGET_PUBLIC_HEADERS
+ libc.include.libintl
libc.include.regex
libc.include.sys_ptrace
)
diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index 7e0511487c2cf5..3bdc686c0e4ce4 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -1708,6 +1708,9 @@ if(LLVM_LIBC_ENABLE_EXPERIMENTAL_ENTRYPOINTS)
libc.src.glob.glob
libc.src.glob.globfree
+ # libintl.h entrypoints
+ libc.src.libintl.textdomain
+
# net/if.h entrypoints
libc.src.net.if_freenameindex
libc.src.net.if_nameindex
diff --git a/libc/config/linux/riscv/headers.txt b/libc/config/linux/riscv/headers.txt
index 19d13a8574bc41..a3c65e50e4e605 100644
--- a/libc/config/linux/riscv/headers.txt
+++ b/libc/config/linux/riscv/headers.txt
@@ -96,6 +96,7 @@ set(TARGET_PUBLIC_HEADERS
if(LLVM_LIBC_FULL_BUILD AND LLVM_LIBC_ENABLE_EXPERIMENTAL_ENTRYPOINTS)
list(APPEND TARGET_PUBLIC_HEADERS
libc.include.glob
+ libc.include.libintl
libc.include.regex
libc.include.sys_ptrace
)
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 155ae28d753bec..23a588f65d7435 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -1734,6 +1734,9 @@ if(LLVM_LIBC_ENABLE_EXPERIMENTAL_ENTRYPOINTS)
libc.src.glob.glob
libc.src.glob.globfree
+ # libintl.h entrypoints
+ libc.src.libintl.textdomain
+
# net/if.h entrypoints
libc.src.net.if_freenameindex
libc.src.net.if_nameindex
diff --git a/libc/config/linux/x86_64/headers.txt b/libc/config/linux/x86_64/headers.txt
index 426972553b93b2..fa37b19e50987f 100644
--- a/libc/config/linux/x86_64/headers.txt
+++ b/libc/config/linux/x86_64/headers.txt
@@ -104,6 +104,7 @@ set(TARGET_PUBLIC_HEADERS
if(LLVM_LIBC_FULL_BUILD AND LLVM_LIBC_ENABLE_EXPERIMENTAL_ENTRYPOINTS)
list(APPEND TARGET_PUBLIC_HEADERS
libc.include.glob
+ libc.include.libintl
libc.include.netdb
libc.include.regex
libc.include.sys_ptrace
diff --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt
index 1c4d7f09c65a6c..73c65cbcb90594 100644
--- a/libc/include/CMakeLists.txt
+++ b/libc/include/CMakeLists.txt
@@ -194,6 +194,15 @@ add_header_macro(
.llvm_libc_common_h
)
+add_header_macro(
+ libintl
+ ../libc/include/libintl.yaml
+ libintl.h
+ DEPENDS
+ .llvm_libc_common_h
+ .llvm-libc-types.locale_t
+)
+
add_header_macro(
limits
../libc/include/limits.yaml
diff --git a/libc/include/libintl.yaml b/libc/include/libintl.yaml
new file mode 100644
index 00000000000000..7e429f3a6b7b20
--- /dev/null
+++ b/libc/include/libintl.yaml
@@ -0,0 +1,15 @@
+header: libintl.h
+standards:
+ - posix
+macros: []
+types:
+ - type_name: locale_t
+enums: []
+objects: []
+functions:
+ - name: textdomain
+ standards:
+ - posix
+ return_type: char *
+ arguments:
+ - type: const char *
diff --git a/libc/src/CMakeLists.txt b/libc/src/CMakeLists.txt
index 0c2d776e5faaea..485259980f7643 100644
--- a/libc/src/CMakeLists.txt
+++ b/libc/src/CMakeLists.txt
@@ -51,6 +51,7 @@ endif()
add_subdirectory(assert)
add_subdirectory(compiler)
+add_subdirectory(libintl)
add_subdirectory(locale)
add_subdirectory(netdb)
add_subdirectory(nl_types)
diff --git a/libc/src/libintl/CMakeLists.txt b/libc/src/libintl/CMakeLists.txt
new file mode 100644
index 00000000000000..063f12227a4b72
--- /dev/null
+++ b/libc/src/libintl/CMakeLists.txt
@@ -0,0 +1,7 @@
+add_entrypoint_object(
+ textdomain
+ SRCS
+ textdomain.cpp
+ HDRS
+ textdomain.h
+)
diff --git a/libc/src/libintl/textdomain.cpp b/libc/src/libintl/textdomain.cpp
new file mode 100644
index 00000000000000..ef5d2f4b20105d
--- /dev/null
+++ b/libc/src/libintl/textdomain.cpp
@@ -0,0 +1,29 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 textdomain (stub).
+///
+//===----------------------------------------------------------------------===//
+
+#include "src/libintl/textdomain.h"
+
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(char *, textdomain, (const char *domainname)) {
+ // TODO: Implement message catalogs. For now, return the default "messages"
+ // domain when querying or resetting, and domainname otherwise.
+ if (domainname == nullptr || domainname[0] == '\0')
+ return const_cast<char *>("messages");
+ return const_cast<char *>(domainname);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/libintl/textdomain.h b/libc/src/libintl/textdomain.h
new file mode 100644
index 00000000000000..bb8df3190c09ef
--- /dev/null
+++ b/libc/src/libintl/textdomain.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 textdomain.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_LIBINTL_TEXTDOMAIN_H
+#define LLVM_LIBC_SRC_LIBINTL_TEXTDOMAIN_H
+
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+char *textdomain(const char *domainname);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_LIBINTL_TEXTDOMAIN_H
diff --git a/libc/test/src/CMakeLists.txt b/libc/test/src/CMakeLists.txt
index 5018f7e15b66da..b4120fa5fe268b 100644
--- a/libc/test/src/CMakeLists.txt
+++ b/libc/test/src/CMakeLists.txt
@@ -126,6 +126,7 @@ endif()
add_subdirectory(assert)
add_subdirectory(compiler)
add_subdirectory(dirent)
+add_subdirectory(libintl)
add_subdirectory(locale)
add_subdirectory(netdb)
add_subdirectory(nl_types)
diff --git a/libc/test/src/libintl/CMakeLists.txt b/libc/test/src/libintl/CMakeLists.txt
new file mode 100644
index 00000000000000..955c5214b53eba
--- /dev/null
+++ b/libc/test/src/libintl/CMakeLists.txt
@@ -0,0 +1,15 @@
+if(LLVM_LIBC_FULL_BUILD AND LLVM_LIBC_ENABLE_EXPERIMENTAL_ENTRYPOINTS)
+ add_custom_target(libc-libintl-tests)
+
+ add_libc_test(
+ libintl_test
+ SUITE
+ libc-libintl-tests
+ SRCS
+ libintl_test.cpp
+ DEPENDS
+ libc.src.libintl.textdomain
+ libc.test.UnitTest.ErrnoCheckingTest
+ libc.test.UnitTest.ErrnoSetterMatcher
+ )
+endif()
diff --git a/libc/test/src/libintl/libintl_test.cpp b/libc/test/src/libintl/libintl_test.cpp
new file mode 100644
index 00000000000000..9f31d16b87bcb0
--- /dev/null
+++ b/libc/test/src/libintl/libintl_test.cpp
@@ -0,0 +1,29 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+/// Unittests for libintl stub functions.
+///
+//===----------------------------------------------------------------------===//
+
+#include "src/libintl/textdomain.h"
+#include "test/UnitTest/ErrnoCheckingTest.h"
+#include "test/UnitTest/ErrnoSetterMatcher.h"
+#include "test/UnitTest/Test.h"
+
+using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds;
+using LlvmLibcLibintlTest = LIBC_NAMESPACE::testing::ErrnoCheckingTest;
+
+TEST_F(LlvmLibcLibintlTest, Textdomain) {
+ EXPECT_STREQ(LIBC_NAMESPACE::textdomain(nullptr), "messages");
+ EXPECT_STREQ(LIBC_NAMESPACE::textdomain(""), "messages");
+
+ constexpr const char *DOMAIN_NAME = "my_app";
+ EXPECT_THAT(LIBC_NAMESPACE::textdomain(DOMAIN_NAME),
+ Succeeds(const_cast<char *>(DOMAIN_NAME)));
+}
More information about the libc-commits
mailing list