[libc-commits] [libc] [libc] Add `ctype.h` locale variants (PR #102711)

via libc-commits libc-commits at lists.llvm.org
Fri Aug 9 19:32:36 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libc

Author: Joseph Huber (jhuber6)

<details>
<summary>Changes</summary>

Summary:
This patch adds all the libc ctype variants. These ignore the locale
ingormation completely, so they're pretty much just stubs. Because these
use locale information, which is system scope, we do not enable building
them outisde of full build mode.


---

Patch is 75.03 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/102711.diff


94 Files Affected:

- (modified) libc/config/gpu/entrypoints.txt (+23) 
- (modified) libc/config/gpu/headers.txt (+1) 
- (modified) libc/config/linux/x86_64/entrypoints.txt (+25) 
- (modified) libc/config/linux/x86_64/headers.txt (+1) 
- (modified) libc/include/CMakeLists.txt (+13) 
- (modified) libc/include/ctype.h.def (+1) 
- (modified) libc/include/llvm-libc-macros/CMakeLists.txt (+6) 
- (added) libc/include/llvm-libc-macros/locale-macros.h (+32) 
- (modified) libc/include/llvm-libc-types/CMakeLists.txt (+2) 
- (added) libc/include/llvm-libc-types/locale_t.h (+22) 
- (added) libc/include/llvm-libc-types/struct_lconv.h (+39) 
- (added) libc/include/locale.h.def (+20) 
- (modified) libc/newhdrgen/yaml/ctype.yaml (+98-1) 
- (added) libc/newhdrgen/yaml/locale.yaml (+41) 
- (modified) libc/spec/stdc.td (+131) 
- (modified) libc/src/CMakeLists.txt (+1) 
- (modified) libc/src/ctype/CMakeLists.txt (+138) 
- (modified) libc/src/ctype/isalnum.cpp (-2) 
- (modified) libc/src/ctype/isalnum.h (+1) 
- (added) libc/src/ctype/isalnum_l.cpp (+21) 
- (added) libc/src/ctype/isalnum_l.h (+21) 
- (modified) libc/src/ctype/isalpha.cpp (-2) 
- (modified) libc/src/ctype/isalpha.h (+1) 
- (added) libc/src/ctype/isalpha_l.cpp (+21) 
- (added) libc/src/ctype/isalpha_l.h (+21) 
- (modified) libc/src/ctype/isascii.h (+1) 
- (modified) libc/src/ctype/isblank.cpp (-2) 
- (modified) libc/src/ctype/isblank.h (+1) 
- (added) libc/src/ctype/isblank_l.cpp (+20) 
- (added) libc/src/ctype/isblank_l.h (+21) 
- (modified) libc/src/ctype/iscntrl.cpp (-2) 
- (modified) libc/src/ctype/iscntrl.h (+1) 
- (added) libc/src/ctype/iscntrl_l.cpp (+21) 
- (added) libc/src/ctype/iscntrl_l.h (+21) 
- (modified) libc/src/ctype/isdigit.cpp (-2) 
- (modified) libc/src/ctype/isdigit.h (+1) 
- (added) libc/src/ctype/isdigit_l.cpp (+20) 
- (added) libc/src/ctype/isdigit_l.h (+21) 
- (modified) libc/src/ctype/isgraph.cpp (-2) 
- (modified) libc/src/ctype/isgraph.h (+1) 
- (added) libc/src/ctype/isgraph_l.cpp (+21) 
- (added) libc/src/ctype/isgraph_l.h (+21) 
- (modified) libc/src/ctype/islower.cpp (-2) 
- (modified) libc/src/ctype/islower.h (+1) 
- (added) libc/src/ctype/islower_l.cpp (+21) 
- (added) libc/src/ctype/islower_l.h (+21) 
- (modified) libc/src/ctype/isprint.cpp (-2) 
- (modified) libc/src/ctype/isprint.h (+1) 
- (added) libc/src/ctype/isprint_l.cpp (+21) 
- (added) libc/src/ctype/isprint_l.h (+21) 
- (modified) libc/src/ctype/ispunct.cpp (-2) 
- (modified) libc/src/ctype/ispunct.h (+1) 
- (added) libc/src/ctype/ispunct_l.cpp (+22) 
- (added) libc/src/ctype/ispunct_l.h (+21) 
- (modified) libc/src/ctype/isspace.cpp (-2) 
- (modified) libc/src/ctype/isspace.h (+1) 
- (added) libc/src/ctype/isspace_l.cpp (+21) 
- (added) libc/src/ctype/isspace_l.h (+21) 
- (modified) libc/src/ctype/isupper.cpp (-2) 
- (modified) libc/src/ctype/isupper.h (+1) 
- (added) libc/src/ctype/isupper_l.cpp (+21) 
- (added) libc/src/ctype/isupper_l.h (+21) 
- (modified) libc/src/ctype/isxdigit.cpp (-2) 
- (modified) libc/src/ctype/isxdigit.h (+1) 
- (added) libc/src/ctype/isxdigit_l.cpp (+22) 
- (added) libc/src/ctype/isxdigit_l.h (+21) 
- (modified) libc/src/ctype/toascii.h (+1) 
- (modified) libc/src/ctype/tolower.cpp (-2) 
- (modified) libc/src/ctype/tolower.h (+1) 
- (added) libc/src/ctype/tolower_l.cpp (+19) 
- (added) libc/src/ctype/tolower_l.h (+21) 
- (modified) libc/src/ctype/toupper.cpp (-2) 
- (modified) libc/src/ctype/toupper.h (+1) 
- (added) libc/src/ctype/toupper_l.cpp (+23) 
- (added) libc/src/ctype/toupper_l.h (+21) 
- (added) libc/src/locale/CMakeLists.txt (+76) 
- (added) libc/src/locale/duplocale.cpp (+21) 
- (added) libc/src/locale/duplocale.h (+22) 
- (added) libc/src/locale/freelocale.cpp (+21) 
- (added) libc/src/locale/freelocale.h (+22) 
- (added) libc/src/locale/locale.cpp (+21) 
- (added) libc/src/locale/locale.h (+36) 
- (added) libc/src/locale/localeconv.cpp (+49) 
- (added) libc/src/locale/localeconv.h (+22) 
- (added) libc/src/locale/newlocale.cpp (+28) 
- (added) libc/src/locale/newlocale.h (+22) 
- (added) libc/src/locale/setlocale.cpp (+28) 
- (added) libc/src/locale/setlocale.h (+22) 
- (added) libc/src/locale/uselocale.cpp (+23) 
- (added) libc/src/locale/uselocale.h (+22) 
- (modified) libc/test/src/CMakeLists.txt (+1) 
- (added) libc/test/src/locale/CMakeLists.txt (+25) 
- (added) libc/test/src/locale/locale_test.cpp (+27) 
- (added) libc/test/src/locale/localeconv_test.cpp (+17) 


``````````diff
diff --git a/libc/config/gpu/entrypoints.txt b/libc/config/gpu/entrypoints.txt
index 5e05c1617a3be0..81602d61ee22ed 100644
--- a/libc/config/gpu/entrypoints.txt
+++ b/libc/config/gpu/entrypoints.txt
@@ -4,21 +4,35 @@ set(TARGET_LIBC_ENTRYPOINTS
 
     # ctype.h entrypoints
     libc.src.ctype.isalnum
+    libc.src.ctype.isalnum_l
     libc.src.ctype.isalpha
+    libc.src.ctype.isalpha_l
     libc.src.ctype.isascii
     libc.src.ctype.isblank
+    libc.src.ctype.isblank_l
     libc.src.ctype.iscntrl
+    libc.src.ctype.iscntrl_l
     libc.src.ctype.isdigit
+    libc.src.ctype.isdigit_l
     libc.src.ctype.isgraph
+    libc.src.ctype.isgraph_l
     libc.src.ctype.islower
+    libc.src.ctype.islower_l
     libc.src.ctype.isprint
+    libc.src.ctype.isprint_l
     libc.src.ctype.ispunct
+    libc.src.ctype.ispunct_l
     libc.src.ctype.isspace
+    libc.src.ctype.isspace_l
     libc.src.ctype.isupper
+    libc.src.ctype.isupper_l
     libc.src.ctype.isxdigit
+    libc.src.ctype.isxdigit_l
     libc.src.ctype.toascii
     libc.src.ctype.tolower
+    libc.src.ctype.tolower_l
     libc.src.ctype.toupper
+    libc.src.ctype.toupper_l
 
     # string.h entrypoints
     libc.src.string.bcmp
@@ -231,6 +245,15 @@ set(TARGET_LIBC_ENTRYPOINTS
     # wchar.h entrypoints
     libc.src.wchar.wctob
 
+    # locale.h entrypoints
+    libc.src.locale.localeconv
+    libc.src.locale.duplocale
+    libc.src.locale.freelocale
+    libc.src.locale.localeconv
+    libc.src.locale.newlocale
+    libc.src.locale.setlocale
+    libc.src.locale.uselocale
+
     # gpu/rpc.h entrypoints
     libc.src.gpu.rpc_host_call
 )
diff --git a/libc/config/gpu/headers.txt b/libc/config/gpu/headers.txt
index 99280b7563a80f..fc952c40f4daa2 100644
--- a/libc/config/gpu/headers.txt
+++ b/libc/config/gpu/headers.txt
@@ -16,6 +16,7 @@ set(TARGET_PUBLIC_HEADERS
     libc.include.wchar
     libc.include.uchar
     libc.include.features
+    libc.include.locale
 
     # Header for RPC extensions
     libc.include.gpu_rpc
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 748401e4cf8ee8..8055bd52e689ac 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -781,6 +781,22 @@ endif()
 
 if(LLVM_LIBC_FULL_BUILD)
   list(APPEND TARGET_LIBC_ENTRYPOINTS
+    # ctype.h entrypoints
+    libc.src.ctype.isalnum_l
+    libc.src.ctype.isalpha_l
+    libc.src.ctype.isblank_l
+    libc.src.ctype.iscntrl_l
+    libc.src.ctype.isdigit_l
+    libc.src.ctype.isgraph_l
+    libc.src.ctype.islower_l
+    libc.src.ctype.isprint_l
+    libc.src.ctype.ispunct_l
+    libc.src.ctype.isspace_l
+    libc.src.ctype.isupper_l
+    libc.src.ctype.isxdigit_l
+    libc.src.ctype.tolower_l
+    libc.src.ctype.toupper_l
+
     # assert.h entrypoints
     libc.src.assert.__assert_fail
 
@@ -981,6 +997,15 @@ if(LLVM_LIBC_FULL_BUILD)
     libc.src.time.nanosleep
     libc.src.time.time
 
+    # locale.h entrypoints
+    libc.src.locale.localeconv
+    libc.src.locale.duplocale
+    libc.src.locale.freelocale
+    libc.src.locale.localeconv
+    libc.src.locale.newlocale
+    libc.src.locale.setlocale
+    libc.src.locale.uselocale
+
     # unistd.h entrypoints
     libc.src.unistd.__llvm_libc_syscall
     libc.src.unistd._exit
diff --git a/libc/config/linux/x86_64/headers.txt b/libc/config/linux/x86_64/headers.txt
index 0294f62bc2f7a0..5a1d970dfe2f96 100644
--- a/libc/config/linux/x86_64/headers.txt
+++ b/libc/config/linux/x86_64/headers.txt
@@ -31,6 +31,7 @@ set(TARGET_PUBLIC_HEADERS
     libc.include.unistd
     libc.include.wchar
     libc.include.uchar
+    libc.include.locale
 
     libc.include.arpa_inet
 
diff --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt
index cbde24e17619f6..a837a305cc79a3 100644
--- a/libc/include/CMakeLists.txt
+++ b/libc/include/CMakeLists.txt
@@ -45,6 +45,7 @@ add_header_macro(
   ctype.h
   DEPENDS
     .llvm_libc_common_h
+    .llvm-libc-types.locale_t
 )
 
 add_header_macro(
@@ -700,6 +701,18 @@ add_header_macro(
     .llvm-libc-types.wchar_t
 )
 
+add_header_macro(
+  locale
+  ../libc/newhdrgen/yaml/locale.yaml
+  locale.h.def
+  locale.h
+  DEPENDS
+    .llvm_libc_common_h
+    .llvm-libc-macros.locale_macros
+    .llvm-libc-types.locale_t
+    .llvm-libc-types.struct_lconv
+)
+
 if(LIBC_TARGET_OS_IS_GPU)
   file(MAKE_DIRECTORY ${LIBC_INCLUDE_DIR}/gpu)
 
diff --git a/libc/include/ctype.h.def b/libc/include/ctype.h.def
index a9bb786931eadf..a6fc61a61fced6 100644
--- a/libc/include/ctype.h.def
+++ b/libc/include/ctype.h.def
@@ -10,6 +10,7 @@
 #define LLVM_LIBC_CTYPE_H
 
 #include "__llvm-libc-common.h"
+#include "llvm-libc-types/locale_t.h"
 
 %%public_api()
 
diff --git a/libc/include/llvm-libc-macros/CMakeLists.txt b/libc/include/llvm-libc-macros/CMakeLists.txt
index 3c10abef8768c0..5fa760d3810af9 100644
--- a/libc/include/llvm-libc-macros/CMakeLists.txt
+++ b/libc/include/llvm-libc-macros/CMakeLists.txt
@@ -289,3 +289,9 @@ add_macro_header(
   HDR
     dlfcn-macros.h
 )
+
+add_macro_header(
+  locale_macros
+  HDR
+    locale-macros.h
+)
diff --git a/libc/include/llvm-libc-macros/locale-macros.h b/libc/include/llvm-libc-macros/locale-macros.h
new file mode 100644
index 00000000000000..892f8b69f3a777
--- /dev/null
+++ b/libc/include/llvm-libc-macros/locale-macros.h
@@ -0,0 +1,32 @@
+//===-- Definition of macros from locale.h --------------------------------===//
+//
+// 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_MACROS_LOCALE_MACROS_H
+#define LLVM_LIBC_MACROS_LOCALE_MACROS_H
+
+#include "../llvm-libc-types/locale_t.h"
+
+#define LC_CTYPE 0
+#define LC_NUMERIC 1
+#define LC_TIME 2
+#define LC_COLLATE 3
+#define LC_MONETARY 4
+#define LC_MESSAGES 5
+#define LC_ALL 6
+
+#define LC_GLOBAL_LOCALE ((locale_t)(-1))
+
+#define LC_CTYPE_MASK (1 << LC_CTYPE)
+#define LC_NUMERIC_MASK (1 << LC_NUMERIC)
+#define LC_TIME_MASK (1 << LC_TIME)
+#define LC_COLLATE_MASK (1 << LC_COLLATE)
+#define LC_MONETARY_MASK (1 << LC_MONETARY)
+#define LC_MESSAGES_MASK (1 << LC_MESSAGES)
+#define LC_ALL_MASK 0x7fffffff
+
+#endif // LLVM_LIBC_MACROS_LOCALE_MACROS_H
diff --git a/libc/include/llvm-libc-types/CMakeLists.txt b/libc/include/llvm-libc-types/CMakeLists.txt
index 0fa86e0152f9ba..583b84ccaae67c 100644
--- a/libc/include/llvm-libc-types/CMakeLists.txt
+++ b/libc/include/llvm-libc-types/CMakeLists.txt
@@ -142,3 +142,5 @@ DEPENDS
   .fsblkcnt_t
   .fsfilcnt_t
 )
+add_header(locale_t HDR locale_t.h)
+add_header(struct_lconv HDR struct_lconv.h)
diff --git a/libc/include/llvm-libc-types/locale_t.h b/libc/include/llvm-libc-types/locale_t.h
new file mode 100644
index 00000000000000..6d783001acf9f2
--- /dev/null
+++ b/libc/include/llvm-libc-types/locale_t.h
@@ -0,0 +1,22 @@
+//===-- Definition of type locale_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_LOCALE_T_H
+#define LLVM_LIBC_TYPES_LOCALE_T_H
+
+#define NUM_LOCALE_CATEGORIES 6
+
+struct __locale_data;
+
+struct __locale_t {
+  struct __locale_data *data[NUM_LOCALE_CATEGORIES];
+};
+
+typedef struct __locale_t *locale_t;
+
+#endif // LLVM_LIBC_TYPES_LOCALE_T_H
diff --git a/libc/include/llvm-libc-types/struct_lconv.h b/libc/include/llvm-libc-types/struct_lconv.h
new file mode 100644
index 00000000000000..9d69f055484dad
--- /dev/null
+++ b/libc/include/llvm-libc-types/struct_lconv.h
@@ -0,0 +1,39 @@
+//===-- Definition of type lconv ------------------------------------------===//
+//
+// 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_LCONV_H
+#define LLVM_LIBC_TYPES_LCONV_H
+
+struct lconv {
+  char *decimal_point;
+  char *thousands_sep;
+  char *grouping;
+  char *mon_decimal_point;
+  char *mon_thousands_sep;
+  char *mon_grouping;
+  char *positive_sign;
+  char *negative_sign;
+  char *currency_symbol;
+  char frac_digits;
+  char p_cs_precedes;
+  char n_cs_precedes;
+  char p_sep_by_space;
+  char n_sep_by_space;
+  char p_sign_posn;
+  char n_sign_posn;
+  char *int_curr_symbol;
+  char int_frac_digits;
+  char int_p_cs_precedes;
+  char int_n_cs_precedes;
+  char int_p_sep_by_space;
+  char int_n_sep_by_space;
+  char int_p_sign_posn;
+  char int_n_sign_posn;
+};
+
+#endif // LLVM_LIBC_TYPES_LCONV_H
diff --git a/libc/include/locale.h.def b/libc/include/locale.h.def
new file mode 100644
index 00000000000000..516c6e6275e681
--- /dev/null
+++ b/libc/include/locale.h.def
@@ -0,0 +1,20 @@
+//===-- C standard library header locale.h --------------------------------===//
+//
+// 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_LOCALE_H
+#define LLVM_LIBC_LOCALE_H
+
+#include "__llvm-libc-common.h"
+
+#include "llvm-libc-macros/locale-macros.h"
+#include "llvm-libc-types/locale_t.h"
+#include "llvm-libc-types/struct_lconv.h"
+
+%%public_api()
+
+#endif // LLVM_LIBC_LOCALE_H
diff --git a/libc/newhdrgen/yaml/ctype.yaml b/libc/newhdrgen/yaml/ctype.yaml
index f3108a34d43377..6fd5581a0e28aa 100644
--- a/libc/newhdrgen/yaml/ctype.yaml
+++ b/libc/newhdrgen/yaml/ctype.yaml
@@ -100,4 +100,101 @@ functions:
     return_type: int
     arguments:
       - type: int
-    functions: null
+  - name: isalnum_l
+    standards:
+      - stdc
+    return_type: int
+    arguments:
+      - type: int
+      - type: locale_t
+  - name: isalpha_l
+    standards:
+      - stdc
+    return_type: int
+    arguments:
+      - type: int
+      - type: locale_t
+  - name: isblank_l
+    standards:
+      - stdc
+    return_type: int
+    arguments:
+      - type: int
+      - type: locale_t
+  - name: iscntrl_l
+    standards:
+      - stdc
+    return_type: int
+    arguments:
+      - type: int
+      - type: locale_t
+  - name: isdigit_l
+    standards:
+      - stdc
+    return_type: int
+    arguments:
+      - type: int
+      - type: locale_t
+  - name: isgraph_l
+    standards:
+      - stdc
+    return_type: int
+    arguments:
+      - type: int
+      - type: locale_t
+  - name: islower_l
+    standards:
+      - stdc
+    return_type: int
+    arguments:
+      - type: int
+      - type: locale_t
+  - name: isprint_l
+    standards:
+      - stdc
+    return_type: int
+    arguments:
+      - type: int
+      - type: locale_t
+  - name: ispunct_l
+    standards:
+      - stdc
+    return_type: int
+    arguments:
+      - type: int
+      - type: locale_t
+  - name: isspace_l
+    standards:
+      - stdc
+    return_type: int
+    arguments:
+      - type: int
+      - type: locale_t
+  - name: isupper_l
+    standards:
+      - stdc
+    return_type: int
+    arguments:
+      - type: int
+      - type: locale_t
+  - name: isxdigit_l
+    standards:
+      - stdc
+    return_type: int
+    arguments:
+      - type: int
+      - type: locale_t
+  - name: tolower_l
+    standards:
+      - stdc
+    return_type: int
+    arguments:
+      - type: int
+      - type: locale_t
+  - name: toupper_l
+    standards:
+      - stdc
+    return_type: int
+    arguments:
+      - type: int
+      - type: locale_t
diff --git a/libc/newhdrgen/yaml/locale.yaml b/libc/newhdrgen/yaml/locale.yaml
new file mode 100644
index 00000000000000..7da7966ea730f6
--- /dev/null
+++ b/libc/newhdrgen/yaml/locale.yaml
@@ -0,0 +1,41 @@
+header: locale.h
+functions:
+  - name: localeconv
+    standards:
+      - stdc
+    return_type: struct lconv *
+    arguments:
+      - type: void
+  - name: duplocale
+    standards:
+      - stdc
+    return_type: locale_t
+    arguments:
+      - type: locale_t
+  - name: freelocale
+    standards:
+      - stdc
+    return_type: void
+    arguments:
+      - type: locale_t
+  - name: newlocale
+    standards:
+      - stdc
+    return_type: locale_t
+    arguments:
+      - type: int
+      - type: const char *
+      - type: locale_t
+  - name: setlocale
+    standards:
+      - stdc
+    return_type: char *
+    arguments:
+      - type: int
+      - type: const char *
+  - name: uselocale
+    standards:
+      - stdc
+    return_type: locale_t
+    arguments:
+      - type: locale_t
diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td
index 077f66e78c1167..b1a949f81559c0 100644
--- a/libc/spec/stdc.td
+++ b/libc/spec/stdc.td
@@ -4,6 +4,11 @@ def StdC : StandardSpec<"stdc"> {
   PtrType StructTmPtr = PtrType<StructTmType>;
   PtrType TimeTTypePtr = PtrType<TimeTType>;
   NamedType ClockT = NamedType<"clock_t">;
+<<<<<<< HEAD
+  NamedType LocaleT = NamedType<"locale_t">;
+=======
+  NamedType LocaleT : NamedType<"locale_t">;
+>>>>>>> a805b5fe17fa ([libc] Add `ctype.h` locale variants)
 
   NamedType DivTType = NamedType<"div_t">;
   NamedType LDivTType = NamedType<"ldiv_t">;
@@ -107,6 +112,76 @@ def StdC : StandardSpec<"stdc"> {
               RetValSpec<IntType>,
               [ArgSpec<IntType>]
           >,
+          FunctionSpec<
+              "isalnum_l",
+              RetValSpec<IntType>,
+              [ArgSpec<IntType>, ArgSpec<LocaleT>]
+          >,
+          FunctionSpec<
+              "isalpha_l",
+              RetValSpec<IntType>,
+              [ArgSpec<IntType>, ArgSpec<LocaleT>]
+          >,
+          FunctionSpec<
+              "isblank_l",
+              RetValSpec<IntType>,
+              [ArgSpec<IntType>, ArgSpec<LocaleT>]
+          >,
+          FunctionSpec<
+              "iscntrl_l",
+              RetValSpec<IntType>,
+              [ArgSpec<IntType>, ArgSpec<LocaleT>]
+          >,
+          FunctionSpec<
+              "isdigit_l",
+              RetValSpec<IntType>,
+              [ArgSpec<IntType>, ArgSpec<LocaleT>]
+          >,
+          FunctionSpec<
+              "isgraph_l",
+              RetValSpec<IntType>,
+              [ArgSpec<IntType>, ArgSpec<LocaleT>]
+          >,
+          FunctionSpec<
+              "islower_l",
+              RetValSpec<IntType>,
+              [ArgSpec<IntType>, ArgSpec<LocaleT>]
+          >,
+          FunctionSpec<
+              "isprint_l",
+              RetValSpec<IntType>,
+              [ArgSpec<IntType>, ArgSpec<LocaleT>]
+          >,
+          FunctionSpec<
+              "ispunct_l",
+              RetValSpec<IntType>,
+              [ArgSpec<IntType>, ArgSpec<LocaleT>]
+          >,
+          FunctionSpec<
+              "isspace_l",
+              RetValSpec<IntType>,
+              [ArgSpec<IntType>, ArgSpec<LocaleT>]
+          >,
+          FunctionSpec<
+              "isupper_l",
+              RetValSpec<IntType>,
+              [ArgSpec<IntType>, ArgSpec<LocaleT>]
+          >,
+          FunctionSpec<
+              "isxdigit_l",
+              RetValSpec<IntType>,
+              [ArgSpec<IntType>, ArgSpec<LocaleT>]
+          >,
+          FunctionSpec<
+              "tolower_l",
+              RetValSpec<IntType>,
+              [ArgSpec<IntType>, ArgSpec<LocaleT>]
+          >,
+          FunctionSpec<
+              "toupper_l",
+              RetValSpec<IntType>,
+              [ArgSpec<IntType>, ArgSpec<LocaleT>]
+          >,
       ]
   >;
 
@@ -1587,6 +1662,61 @@ def StdC : StandardSpec<"stdc"> {
       ]
   >;
 
+  
+  NamedType StructLconv : NamedType<"struct lconv">;
+  PtrType StructLconvPtr : PtrType<StructLconv>;
+
+  HeaderSpec Locale = HeaderSpec<
+     "locale.h",
+      [], // Macros
+      [LocaleT, StructLconv], // Types
+      [], // Enumerations
+      [
+        FunctionSpec<
+          "duplocale",
+          RetValSpec<LocaleT>,
+          [
+            ArgSpec<LocaleT>
+          ]
+        >,
+        FunctionSpec<
+          "freelocale",
+          RetValSpec<VoidType>,
+          [
+            ArgSpec<LocaleT>
+          ]
+        >,
+        FunctionSpec<
+          "localeconv",
+          RetValSpec<StructLconvPtr>,
+          []
+        >,
+        FunctionSpec<
+          "newlocale",
+          RetValSpec<LocaleT>,
+          [
+            ArgSpec<IntType>,
+            ArgSpec<ConstCharPtr>,
+            ArgSpec<LocaleT>
+          ]
+        >,
+        FunctionSpec<
+          "setlocale",
+          RetValSpec<CharPtr>,
+          [
+            ArgSpec<IntType>,
+            ArgSpec<ConstCharPtr>
+          ]
+        >,
+        FunctionSpec<
+          "uselocale",
+          RetValSpec<LocaleT>,
+          [
+            ArgSpec<LocaleT>
+          ]
+        >
+      ]  // Functions
+  >;
 
   let Headers = [
     Assert,
@@ -1609,5 +1739,6 @@ def StdC : StandardSpec<"stdc"> {
     Time,
     UChar,
     WChar,
+    Locale,
   ];
 }
diff --git a/libc/src/CMakeLists.txt b/libc/src/CMakeLists.txt
index 9597e2380172b5..d554c12fb1ec89 100644
--- a/libc/src/CMakeLists.txt
+++ b/libc/src/CMakeLists.txt
@@ -40,3 +40,4 @@ add_subdirectory(signal)
 add_subdirectory(spawn)
 add_subdirectory(threads)
 add_subdirectory(time)
+add_subdirectory(locale)
diff --git a/libc/src/ctype/CMakeLists.txt b/libc/src/ctype/CMakeLists.txt
index ae4eec9615dc19..15fca7ae6531cf 100644
--- a/libc/src/ctype/CMakeLists.txt
+++ b/libc/src/ctype/CMakeLists.txt
@@ -146,3 +146,141 @@ add_entrypoint_object(
   DEPENDS
     libc.src.__support.ctype_utils
 )
+
+# Do not build the locale versions in overlay mode.
+if(NOT LLVM_LIBC_FULL_BUILD)
+  return()
+endif()
+
+add_entrypoint_object(
+  isalnum_l
+  SRCS
+    isalnum_l.cpp
+  HDRS
+    isalnum_l.h
+  DEPENDS
+    libc.include.ctype
+    libc.src.__support.ctype_utils
+)
+
+add_entrypoint_object(
+  isalpha_l
+  SRCS
+    isalpha_l.cpp
+  HDRS
+    isalpha_l.h
+  DEPENDS
+    libc.src.__support.ctype_utils
+)
+
+add_entrypoint_object(
+  isblank_l
+  SRCS
+    isblank_l.cpp
+  HDRS
+    isblank_l.h
+)
+
+add_entrypoint_object(
+  iscntrl_l
+  SRCS
+    iscntrl_l.cpp
+  HDRS
+    iscntrl_l.h
+)
+
+add_entrypoint_object(
+  isdigit_l
+  SRCS
+    isdigit_l.cpp
+  HDRS
+    isdigit_l.h
+  DEPENDS
+    libc.src.__support.ctype_utils
+)
+
+add_entrypoint_object(
+  isgraph_l
+  SRCS
+    isgraph_l.cpp
+  HDRS
+    isgraph_l.h
+  DEPENDS
+    libc.src.__support.ctype_utils
+)
+
+add_entrypoint_object(
+  islower_l
+  SRCS
+    islower_l.cpp
+  HDRS
+    islower_l.h
+  DEPENDS
+    libc.src.__support.ctype_utils
+)
+
+add_entrypoint_object(
+  isprint_l
+  SRCS
+    isprint_l.cpp
+  HDRS
+    isprint_l.h
+)
+
+add_entrypoint_object(
+  ispunct_l
+  SRCS
+    ispunct_l.cpp
+  HDRS
+    ispunct_l.h
+  DEPENDS
+    libc.src.__support.ctype_utils
+)
+
+add_entrypoint_object(
+  isspace_l
+  SRCS
+    isspace_l.cpp
+  HDRS
+    isspace_l.h
+)
+
+add_entrypoint_object(
+  isupper_l
+  SRCS
+    isupper_l.cpp
+  HDRS
+    isupper_l.h
+  DEPENDS
+    libc.src.__support.ctype_utils
+)
+
+add_entrypoint_object(
+  isxdigit_l
+  SRCS
+    isxdigit_l.cpp
+  HDRS
+    isxdigit_l.h
+  DEPENDS
+    libc.src.__support.ctype_utils
+)
+
+add_entrypoint_object(
+  tolower_l
+  SRCS
+    tolower_l.cpp
+  HDRS
+    tolower_l.h
+  DEPENDS
+    libc.src.__support.ctype_utils
+)
+
+add_entrypoint_object(
+  toupper_l
+  SRCS
+    toupper_l.cpp
+  HDRS
+    toupper_l.h
+  DEPENDS
+    libc.src.__support.ctype_utils
+)
diff --git a/libc/src/ctype/isalnum.cpp b/libc/src/ctype/isalnum.cpp
index 382553c23a6bfb..54a3e357488790 100644
--- a/libc/src/ctype/isalnum.cpp
+++ b/libc/src/ctype/isalnum.cpp
@@ -14,8 +14,6 @@
 
 namespace LIBC_NAMESPACE_DECL {
 
-// TODO: Currently restricted to default locale.
-// These should be extended using locale information.
 LLVM_LIBC_FUNCTION(int, isalnum, (int c)) {
   return static_cast<int>(internal::isalnum(static_cast<unsigned>(c)));
 }
diff --git a/libc/src/ctype/isalnum.h b/libc/src/ctype/isalnum.h
index 6516f2ebc327d1..5b55cdcf5ba56d 1006...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/102711


More information about the libc-commits mailing list