[libc-commits] [libc] e4693c0 - [libc] Add __isoc99_fscanf alias. (#213125)

via libc-commits libc-commits at lists.llvm.org
Sun Aug 2 08:13:22 PDT 2026


Author: lntue
Date: 2026-08-02T11:13:17-04:00
New Revision: e4693c0579ed0f3df45a06b918d448795b738a58

URL: https://github.com/llvm/llvm-project/commit/e4693c0579ed0f3df45a06b918d448795b738a58
DIFF: https://github.com/llvm/llvm-project/commit/e4693c0579ed0f3df45a06b918d448795b738a58.diff

LOG: [libc] Add __isoc99_fscanf alias. (#213125)

- Add LLVM_LIBC_ADD_FUNCTION_C_ALIAS macro to add another C alias public
symbol to a function.
- Add LIBC_CONF_SCANF_PROVIDE_ISOC99_ALIASES config
- Add __isoc99_fscanf for generic fscanf target if
LIBC_CONF_SCANF_PROVIDE_ISOC99_ALIASES is set.
- Similarly: scanf, vfscanf, vscanf.

Added: 
    

Modified: 
    libc/CMakeLists.txt
    libc/cmake/modules/LLVMLibCCompileOptionRules.cmake
    libc/cmake/modules/LibcConfig.cmake
    libc/config/config.json
    libc/config/linux/config.json
    libc/src/__support/common.h
    libc/src/stdio/generic/fscanf.cpp
    libc/src/stdio/generic/scanf.cpp
    libc/src/stdio/generic/vfscanf.cpp
    libc/src/stdio/generic/vscanf.cpp
    libc/src/stdio/sscanf.cpp
    libc/src/stdio/vsscanf.cpp

Removed: 
    


################################################################################
diff  --git a/libc/CMakeLists.txt b/libc/CMakeLists.txt
index c5dea3100f053..7e42ba2a76df2 100644
--- a/libc/CMakeLists.txt
+++ b/libc/CMakeLists.txt
@@ -152,6 +152,11 @@ if(LIBC_TARGET_OS_IS_GPU)
 endif()
 
 option(LLVM_LIBC_FULL_BUILD "Build and test LLVM libc as if it is the full libc" ${default_to_full_build})
+if(LLVM_LIBC_FULL_BUILD)
+  set(LLVM_LIBC_OVERLAY OFF)
+else()
+  set(LLVM_LIBC_OVERLAY ON)
+endif()
 option(LLVM_LIBC_IMPLEMENTATION_DEFINED_TEST_BEHAVIOR "Build LLVM libc tests assuming our implementation-defined behavior" ON)
 option(LLVM_LIBC_ENABLE_LINTING "Enables linting of libc source files" OFF)
 option(LLVM_LIBC_ALL_HEADERS "Outputs all functions in header files, regardless of whether they are enabled on this target" OFF)

diff  --git a/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake b/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake
index 600df74f552b0..4f8f3f5d13b82 100644
--- a/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake
+++ b/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake
@@ -193,6 +193,10 @@ function(_get_compile_options_from_config output_var)
     list(APPEND config_options "-DLIBC_COPT_USE_C_ASSERT")
   endif()
 
+  if(LIBC_CONF_SCANF_PROVIDE_ISOC99_ALIASES)
+    list(APPEND config_options "-DLIBC_COPT_SCANF_PROVIDE_ISOC99_ALIASES")
+  endif()
+
   set(${output_var} ${config_options} PARENT_SCOPE)
 endfunction(_get_compile_options_from_config)
 

diff  --git a/libc/cmake/modules/LibcConfig.cmake b/libc/cmake/modules/LibcConfig.cmake
index 19bdf44d96bfc..dd6e3cf49375c 100644
--- a/libc/cmake/modules/LibcConfig.cmake
+++ b/libc/cmake/modules/LibcConfig.cmake
@@ -37,7 +37,9 @@ function(read_libc_config config_file opt_list)
     DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
     PROPERTY CMAKE_CONFIGURE_DEPENDS ${config_file})
 
-  file(READ ${config_file} json_config)
+  file(READ ${config_file} json_config_raw)
+  # Expand all CMake variables in the JSON string first
+  string(CONFIGURE "${json_config_raw}" json_config)
   string(JSON group_count ERROR_VARIABLE json_error LENGTH ${json_config})
   if(json_error)
     message(FATAL_ERROR "${config_file}: ${json_error}")

diff  --git a/libc/config/config.json b/libc/config/config.json
index d576d7d14e4af..01909fb9abf8a 100644
--- a/libc/config/config.json
+++ b/libc/config/config.json
@@ -73,6 +73,10 @@
     "LIBC_CONF_SCANF_DISABLE_INDEX_MODE": {
       "value": false,
       "doc": "Disable index mode in the scanf format string."
+    },
+    "LIBC_CONF_SCANF_PROVIDE_ISOC99_ALIASES": {
+      "value": false,
+      "doc": "Add __isoc99_* aliases for scanf's functions."
     }
   },
   "str_to_float": {

diff  --git a/libc/config/linux/config.json b/libc/config/linux/config.json
index a3676986721b4..260ec3b43f72c 100644
--- a/libc/config/linux/config.json
+++ b/libc/config/linux/config.json
@@ -1,4 +1,9 @@
 {
+  "scanf": {
+    "LIBC_CONF_SCANF_PROVIDE_ISOC99_ALIASES": {
+      "value": "${LLVM_LIBC_OVERLAY}"
+    }
+  },
   "string": {
     "LIBC_CONF_STRING_LENGTH_IMPL": {
       "value": "clang_vector"

diff  --git a/libc/src/__support/common.h b/libc/src/__support/common.h
index 8a8ffefd381ee..e142eb815f2fa 100644
--- a/libc/src/__support/common.h
+++ b/libc/src/__support/common.h
@@ -61,17 +61,33 @@
       __##name##_impl__ asm(c_alias);                                          \
   decltype(LIBC_NAMESPACE::name) name [[gnu::alias(c_alias)]];                 \
   type __##name##_impl__ arglist
+
+#define LLVM_LIBC_ADD_FUNCTION_C_ALIAS(name, c_alias)                          \
+  extern "C" decltype(LIBC_NAMESPACE::name) c_alias [[gnu::alias(#name)]]
+
 #else // LIBC_TARGET_USES_LEADING_UNDERSCORE
 #define LLVM_LIBC_FUNCTION_IMPL_4(type, name, arglist, c_alias)                \
   LLVM_LIBC_ATTR(name)                                                         \
   LLVM_LIBC_FUNCTION_ATTR decltype(LIBC_NAMESPACE::name) name asm(             \
       "_" c_alias);                                                            \
   type name arglist
+
+// clang-format off
+#define LLVM_LIBC_ADD_FUNCTION_C_ALIAS(name, c_alias)                          \
+  asm(".text\n"                                                                \
+      ".global " "_" #c_alias "\n"                                             \
+      ".type " "_" #c_alias ", @function\n"                                    \
+      "_" #c_alias " = " "_" #name "\n")
+// clang-format on
 #endif // LIBC_TARGET_USES_LEADING_UNDERSCORE
 
 #else  // LIBC_COPT_PUBLIC_PACKAGING
 #define LLVM_LIBC_FUNCTION_IMPL_4(type, name, arglist, c_alias)                \
   type name arglist
+
+#define LLVM_LIBC_ADD_FUNCTION_C_ALIAS(name, c_alias)                          \
+  static_assert(true, "Require semicolon.")
+
 #endif // LIBC_COPT_PUBLIC_PACKAGING
 
 #define LLVM_LIBC_FUNCTION_IMPL_3(type, name, arglist)                         \

diff  --git a/libc/src/stdio/generic/fscanf.cpp b/libc/src/stdio/generic/fscanf.cpp
index 94b843978749e..f0f6c627b5054 100644
--- a/libc/src/stdio/generic/fscanf.cpp
+++ b/libc/src/stdio/generic/fscanf.cpp
@@ -34,3 +34,7 @@ LLVM_LIBC_FUNCTION(int, fscanf,
 }
 
 } // namespace LIBC_NAMESPACE_DECL
+
+#ifdef LIBC_COPT_SCANF_PROVIDE_ISOC99_ALIASES
+LLVM_LIBC_ADD_FUNCTION_C_ALIAS(fscanf, __isoc99_fscanf);
+#endif // LIBC_COPT_SCANF_PROVIDE_ISOC99_ALIASES

diff  --git a/libc/src/stdio/generic/scanf.cpp b/libc/src/stdio/generic/scanf.cpp
index 37b7ee7d7ca36..f0607c6c8b6ab 100644
--- a/libc/src/stdio/generic/scanf.cpp
+++ b/libc/src/stdio/generic/scanf.cpp
@@ -40,3 +40,7 @@ LLVM_LIBC_FUNCTION(int, scanf, (const char *__restrict format, ...)) {
 }
 
 } // namespace LIBC_NAMESPACE_DECL
+
+#ifdef LIBC_COPT_SCANF_PROVIDE_ISOC99_ALIASES
+LLVM_LIBC_ADD_FUNCTION_C_ALIAS(scanf, __isoc99_scanf);
+#endif // LIBC_COPT_SCANF_PROVIDE_ISOC99_ALIASES

diff  --git a/libc/src/stdio/generic/vfscanf.cpp b/libc/src/stdio/generic/vfscanf.cpp
index 220576522d0fd..5976e61b857c5 100644
--- a/libc/src/stdio/generic/vfscanf.cpp
+++ b/libc/src/stdio/generic/vfscanf.cpp
@@ -32,3 +32,7 @@ LLVM_LIBC_FUNCTION(int, vfscanf,
 }
 
 } // namespace LIBC_NAMESPACE_DECL
+
+#ifdef LIBC_COPT_SCANF_PROVIDE_ISOC99_ALIASES
+LLVM_LIBC_ADD_FUNCTION_C_ALIAS(vfscanf, __isoc99_vfscanf);
+#endif // LIBC_COPT_SCANF_PROVIDE_ISOC99_ALIASES

diff  --git a/libc/src/stdio/generic/vscanf.cpp b/libc/src/stdio/generic/vscanf.cpp
index 215ba790b241c..ea82c5edb729a 100644
--- a/libc/src/stdio/generic/vscanf.cpp
+++ b/libc/src/stdio/generic/vscanf.cpp
@@ -39,3 +39,7 @@ LLVM_LIBC_FUNCTION(int, vscanf,
 }
 
 } // namespace LIBC_NAMESPACE_DECL
+
+#ifdef LIBC_COPT_SCANF_PROVIDE_ISOC99_ALIASES
+LLVM_LIBC_ADD_FUNCTION_C_ALIAS(vscanf, __isoc99_vscanf);
+#endif // LIBC_COPT_SCANF_PROVIDE_ISOC99_ALIASES

diff  --git a/libc/src/stdio/sscanf.cpp b/libc/src/stdio/sscanf.cpp
index 9fa2ede461595..85f7a3a2869f5 100644
--- a/libc/src/stdio/sscanf.cpp
+++ b/libc/src/stdio/sscanf.cpp
@@ -37,3 +37,7 @@ LLVM_LIBC_FUNCTION(int, sscanf,
 }
 
 } // namespace LIBC_NAMESPACE_DECL
+
+#ifdef LIBC_COPT_SCANF_PROVIDE_ISOC99_ALIASES
+LLVM_LIBC_ADD_FUNCTION_C_ALIAS(sscanf, __isoc99_sscanf);
+#endif // LIBC_COPT_SCANF_PROVIDE_ISOC99_ALIASES

diff  --git a/libc/src/stdio/vsscanf.cpp b/libc/src/stdio/vsscanf.cpp
index 7c7240a102b5a..f46754a48e97a 100644
--- a/libc/src/stdio/vsscanf.cpp
+++ b/libc/src/stdio/vsscanf.cpp
@@ -29,3 +29,7 @@ LLVM_LIBC_FUNCTION(int, vsscanf,
 }
 
 } // namespace LIBC_NAMESPACE_DECL
+
+#ifdef LIBC_COPT_SCANF_PROVIDE_ISOC99_ALIASES
+LLVM_LIBC_ADD_FUNCTION_C_ALIAS(vsscanf, __isoc99_vsscanf);
+#endif // LIBC_COPT_SCANF_PROVIDE_ISOC99_ALIASES


        


More information about the libc-commits mailing list