Skip to content
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

[libc] Templatize the scanf Reader interface #131037

Merged
merged 4 commits into from
Mar 18, 2025

Conversation

petrhosek
Copy link
Member

This allows specializing the implementation for different targets without including unnecessary logic and is similar to #111559 which did the same for printf Writer interface.

@llvmbot
Copy link
Member

llvmbot commented Mar 12, 2025

@llvm/pr-subscribers-libc

Author: Petr Hosek (petrhosek)

Changes

This allows specializing the implementation for different targets without including unnecessary logic and is similar to #111559 which did the same for printf Writer interface.


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

32 Files Affected:

  • (modified) libc/config/baremetal/aarch64/entrypoints.txt (+6-2)
  • (modified) libc/config/baremetal/arm/entrypoints.txt (+6-2)
  • (modified) libc/config/baremetal/riscv/entrypoints.txt (+6-2)
  • (modified) libc/src/stdio/CMakeLists.txt (+4-54)
  • (modified) libc/src/stdio/baremetal/CMakeLists.txt (+26)
  • (added) libc/src/stdio/baremetal/scanf.cpp (+52)
  • (added) libc/src/stdio/baremetal/vscanf.cpp (+51)
  • (modified) libc/src/stdio/generic/CMakeLists.txt (+54)
  • (renamed) libc/src/stdio/generic/fscanf.cpp ()
  • (renamed) libc/src/stdio/generic/scanf.cpp ()
  • (renamed) libc/src/stdio/generic/vfscanf.cpp ()
  • (renamed) libc/src/stdio/generic/vscanf.cpp ()
  • (modified) libc/src/stdio/scanf_core/CMakeLists.txt (+4-17)
  • (modified) libc/src/stdio/scanf_core/converter.cpp (-73)
  • (modified) libc/src/stdio/scanf_core/converter.h (+81-2)
  • (modified) libc/src/stdio/scanf_core/current_pos_converter.h (+2-1)
  • (removed) libc/src/stdio/scanf_core/float_converter.cpp (-229)
  • (modified) libc/src/stdio/scanf_core/float_converter.h (+208-1)
  • (removed) libc/src/stdio/scanf_core/int_converter.cpp (-230)
  • (modified) libc/src/stdio/scanf_core/int_converter.h (+209-1)
  • (removed) libc/src/stdio/scanf_core/ptr_converter.cpp (-46)
  • (modified) libc/src/stdio/scanf_core/ptr_converter.h (+26-1)
  • (modified) libc/src/stdio/scanf_core/reader.h (+31-87)
  • (removed) libc/src/stdio/scanf_core/scanf_main.cpp (-46)
  • (modified) libc/src/stdio/scanf_core/scanf_main.h (+25-2)
  • (removed) libc/src/stdio/scanf_core/string_converter.cpp (-77)
  • (modified) libc/src/stdio/scanf_core/string_converter.h (+56-1)
  • (modified) libc/src/stdio/scanf_core/vfscanf_internal.h (+39-1)
  • (modified) libc/src/stdio/sscanf.cpp (+2-2)
  • (modified) libc/src/stdio/vsscanf.cpp (+3-3)
  • (modified) libc/test/src/stdio/scanf_core/converter_test.cpp (+21-14)
  • (modified) libc/test/src/stdio/scanf_core/reader_test.cpp (+9-6)
diff --git a/libc/config/baremetal/aarch64/entrypoints.txt b/libc/config/baremetal/aarch64/entrypoints.txt
index 2c226ef176c08..8b51942d30fe8 100644
--- a/libc/config/baremetal/aarch64/entrypoints.txt
+++ b/libc/config/baremetal/aarch64/entrypoints.txt
@@ -123,18 +123,22 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.inttypes.strtoumax
 
     # stdio.h entrypoints
+    libc.src.stdio.asprintf
     libc.src.stdio.getchar
     libc.src.stdio.printf
     libc.src.stdio.putchar
     libc.src.stdio.puts
     libc.src.stdio.remove
+    libc.src.stdio.scanf
     libc.src.stdio.snprintf
     libc.src.stdio.sprintf
-    libc.src.stdio.asprintf
+    libc.src.stdio.sscanf
+    libc.src.stdio.vasprintf
     libc.src.stdio.vprintf
+    libc.src.stdio.vscanf
     libc.src.stdio.vsnprintf
     libc.src.stdio.vsprintf
-    libc.src.stdio.vasprintf
+    libc.src.stdio.vsscanf
 
     # stdbit.h entrypoints
     libc.src.stdbit.stdc_bit_ceil_uc
diff --git a/libc/config/baremetal/arm/entrypoints.txt b/libc/config/baremetal/arm/entrypoints.txt
index d7a01bdf90b3f..511d9d22f1450 100644
--- a/libc/config/baremetal/arm/entrypoints.txt
+++ b/libc/config/baremetal/arm/entrypoints.txt
@@ -123,18 +123,22 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.inttypes.strtoumax
 
     # stdio.h entrypoints
+    libc.src.stdio.asprintf
     libc.src.stdio.getchar
     libc.src.stdio.printf
     libc.src.stdio.putchar
     libc.src.stdio.puts
     libc.src.stdio.remove
+    libc.src.stdio.scanf
     libc.src.stdio.snprintf
     libc.src.stdio.sprintf
-    libc.src.stdio.asprintf
+    libc.src.stdio.sscanf
+    libc.src.stdio.vasprintf
     libc.src.stdio.vprintf
+    libc.src.stdio.vscanf
     libc.src.stdio.vsnprintf
     libc.src.stdio.vsprintf
-    libc.src.stdio.vasprintf
+    libc.src.stdio.vsscanf
 
     # stdbit.h entrypoints
     libc.src.stdbit.stdc_bit_ceil_uc
diff --git a/libc/config/baremetal/riscv/entrypoints.txt b/libc/config/baremetal/riscv/entrypoints.txt
index ae00803dd0def..bbefb75ee16b5 100644
--- a/libc/config/baremetal/riscv/entrypoints.txt
+++ b/libc/config/baremetal/riscv/entrypoints.txt
@@ -119,18 +119,22 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.inttypes.strtoumax
 
     # stdio.h entrypoints
+    libc.src.stdio.asprintf
     libc.src.stdio.getchar
     libc.src.stdio.printf
     libc.src.stdio.putchar
     libc.src.stdio.puts
     libc.src.stdio.remove
+    libc.src.stdio.scanf
     libc.src.stdio.snprintf
     libc.src.stdio.sprintf
-    libc.src.stdio.asprintf
+    libc.src.stdio.sscanf
+    libc.src.stdio.vasprintf
     libc.src.stdio.vprintf
+    libc.src.stdio.vscanf
     libc.src.stdio.vsnprintf
     libc.src.stdio.vsprintf
-    libc.src.stdio.vasprintf
+    libc.src.stdio.vsscanf
 
     # stdbit.h entrypoints
     libc.src.stdbit.stdc_bit_ceil_uc
diff --git a/libc/src/stdio/CMakeLists.txt b/libc/src/stdio/CMakeLists.txt
index b9bc904471df9..23c103c1d6465 100644
--- a/libc/src/stdio/CMakeLists.txt
+++ b/libc/src/stdio/CMakeLists.txt
@@ -95,20 +95,6 @@ add_entrypoint_object(
     libc.src.__support.File.platform_file
 )
 
-list(APPEND scanf_deps
-      libc.src.__support.arg_list
-      libc.src.stdio.scanf_core.vfscanf_internal
-      libc.hdr.types.FILE
-)
-
-if(LLVM_LIBC_FULL_BUILD AND NOT LIBC_TARGET_OS_IS_GPU)
-  list(APPEND scanf_deps
-      libc.src.__support.File.file
-      libc.src.__support.File.platform_file
-      libc.src.__support.File.platform_stdin
-  )
-endif()
-
 add_entrypoint_object(
   sscanf
   SRCS
@@ -133,46 +119,6 @@ add_entrypoint_object(
     libc.src.stdio.scanf_core.scanf_main
 )
 
-add_entrypoint_object(
-  fscanf
-  SRCS
-    fscanf.cpp
-  HDRS
-    fscanf.h
-  DEPENDS
-    ${scanf_deps}
-)
-
-add_entrypoint_object(
-  vfscanf
-  SRCS
-    vfscanf.cpp
-  HDRS
-    vfscanf.h
-  DEPENDS
-    ${scanf_deps}
-)
-
-add_entrypoint_object(
-  scanf
-  SRCS
-    scanf.cpp
-  HDRS
-    scanf.h
-  DEPENDS
-    ${scanf_deps}
-)
-
-add_entrypoint_object(
-  vscanf
-  SRCS
-    vscanf.cpp
-  HDRS
-    vscanf.h
-  DEPENDS
-    ${scanf_deps}
-)
-
 add_entrypoint_object(
   sprintf
   SRCS
@@ -295,8 +241,12 @@ add_stdio_entrypoint_object(getchar)
 add_stdio_entrypoint_object(getchar_unlocked)
 add_stdio_entrypoint_object(fgets)
 add_stdio_entrypoint_object(ungetc)
+add_stdio_entrypoint_object(scanf)
+add_stdio_entrypoint_object(fscanf)
 add_stdio_entrypoint_object(stdin)
 add_stdio_entrypoint_object(stdout)
 add_stdio_entrypoint_object(stderr)
 add_stdio_entrypoint_object(vprintf)
 add_stdio_entrypoint_object(vfprintf)
+add_stdio_entrypoint_object(vscanf)
+add_stdio_entrypoint_object(vfscanf)
diff --git a/libc/src/stdio/baremetal/CMakeLists.txt b/libc/src/stdio/baremetal/CMakeLists.txt
index c5cf4a8e0e5b5..4abe8bc66b25b 100644
--- a/libc/src/stdio/baremetal/CMakeLists.txt
+++ b/libc/src/stdio/baremetal/CMakeLists.txt
@@ -55,6 +55,19 @@ add_entrypoint_object(
     libc.src.__support.CPP.string_view
 )
 
+add_entrypoint_object(
+  scanf
+  SRCS
+    scanf.cpp
+  HDRS
+    ../scanf.h
+  DEPENDS
+    libc.src.stdio.scanf_core.scanf_main
+    libc.src.stdio.scanf_core.reader
+    libc.src.__support.arg_list
+    libc.src.__support.OSUtil.osutil
+)
+
 add_entrypoint_object(
   vprintf
   SRCS
@@ -67,3 +80,16 @@ add_entrypoint_object(
     libc.src.__support.arg_list
     libc.src.__support.OSUtil.osutil
 )
+
+add_entrypoint_object(
+  vscanf
+  SRCS
+    vscanf.cpp
+  HDRS
+    ../vscanf.h
+  DEPENDS
+    libc.src.stdio.scanf_core.scanf_main
+    libc.src.stdio.scanf_core.reader
+    libc.src.__support.arg_list
+    libc.src.__support.OSUtil.osutil
+)
diff --git a/libc/src/stdio/baremetal/scanf.cpp b/libc/src/stdio/baremetal/scanf.cpp
new file mode 100644
index 0000000000000..1b0bf3e3afd54
--- /dev/null
+++ b/libc/src/stdio/baremetal/scanf.cpp
@@ -0,0 +1,52 @@
+//===-- Implementation of scanf ---------------------------------*- C++ -*-===//
+//
+// 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/stdio/scanf.h"
+
+#include "hdr/stdio_macros.h"
+#include "src/__support/OSUtil/io.h"
+#include "src/__support/arg_list.h"
+#include "src/__support/macros/config.h"
+#include "src/stdio/scanf_core/reader.h"
+#include "src/stdio/scanf_core/scanf_main.h"
+
+#include <stdarg.h>
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace {
+
+struct StreamBuffer : scanf_core::ReadBuffer<StreamBuffer> {
+  LIBC_INLINE char getc() {
+    char buf[1];
+    read_from_stdin(buf, sizeof(buf));
+    return buf[0];
+  }
+  LIBC_INLINE void ungetc(int) {}
+};
+
+} // namespace
+
+LLVM_LIBC_FUNCTION(int, scanf, (const char *__restrict format, ...)) {
+  va_list vlist;
+  va_start(vlist, format);
+  internal::ArgList args(vlist); // This holder class allows for easier copying
+                                 // and pointer semantics, as well as handling
+                                 // destruction automatically.
+  va_end(vlist);
+
+  StreamBuffer buffer;
+  scanf_core::Reader<StreamBuffer> reader(&buffer);
+
+  int retval = scanf_core::scanf_main(&reader, format, args);
+  // This is done to avoid including stdio.h in the internals. On most systems
+  // EOF is -1, so this will be transformed into just "return retval".
+  return (retval == -1) ? EOF : retval;
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdio/baremetal/vscanf.cpp b/libc/src/stdio/baremetal/vscanf.cpp
new file mode 100644
index 0000000000000..e0119d6146d89
--- /dev/null
+++ b/libc/src/stdio/baremetal/vscanf.cpp
@@ -0,0 +1,51 @@
+//===-- Implementation of vscanf --------------------------------*- C++ -*-===//
+//
+// 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/stdio/vscanf.h"
+
+#include "hdr/stdio_macros.h"
+#include "src/__support/OSUtil/io.h"
+#include "src/__support/arg_list.h"
+#include "src/__support/macros/config.h"
+#include "src/stdio/scanf_core/reader.h"
+#include "src/stdio/scanf_core/scanf_main.h"
+
+#include <stdarg.h>
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace {
+
+struct StreamBuffer : scanf_core::ReadBuffer<StreamBuffer> {
+  LIBC_INLINE char getc() {
+    char buf[1];
+    read_from_stdin(buf, sizeof(buf));
+    return buf[0];
+  }
+  LIBC_INLINE void ungetc(int) {}
+};
+
+} // namespace
+
+LLVM_LIBC_FUNCTION(int, vscanf,
+                   (const char *__restrict format, va_list vlist)) {
+  internal::ArgList args(vlist); // This holder class allows for easier copying
+                                 // and pointer semantics, as well as handling
+                                 // destruction automatically.
+  va_end(vlist);
+
+  StreamBuffer buffer;
+  scanf_core::Reader<StreamBuffer> reader(&buffer);
+
+  int retval = scanf_core::scanf_main(&reader, format, args);
+  // This is done to avoid including stdio.h in the internals. On most systems
+  // EOF is -1, so this will be transformed into just "return retval".
+  return (retval == -1) ? EOF : retval;
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdio/generic/CMakeLists.txt b/libc/src/stdio/generic/CMakeLists.txt
index bf301a6b0cb3c..9f568c5ab8d3a 100644
--- a/libc/src/stdio/generic/CMakeLists.txt
+++ b/libc/src/stdio/generic/CMakeLists.txt
@@ -425,6 +425,60 @@ add_entrypoint_object(
     ${fprintf_deps}
 )
 
+list(APPEND scanf_deps
+      libc.src.__support.arg_list
+      libc.src.stdio.scanf_core.vfscanf_internal
+      libc.hdr.types.FILE
+)
+
+if(LLVM_LIBC_FULL_BUILD AND NOT LIBC_TARGET_OS_IS_GPU)
+  list(APPEND scanf_deps
+      libc.src.__support.File.file
+      libc.src.__support.File.platform_file
+      libc.src.__support.File.platform_stdin
+  )
+endif()
+
+add_entrypoint_object(
+  fscanf
+  SRCS
+    fscanf.cpp
+  HDRS
+    ../fscanf.h
+  DEPENDS
+    ${scanf_deps}
+)
+
+add_entrypoint_object(
+  vfscanf
+  SRCS
+    vfscanf.cpp
+  HDRS
+    ../vfscanf.h
+  DEPENDS
+    ${scanf_deps}
+)
+
+add_entrypoint_object(
+  scanf
+  SRCS
+    scanf.cpp
+  HDRS
+    ../scanf.h
+  DEPENDS
+    ${scanf_deps}
+)
+
+add_entrypoint_object(
+  vscanf
+  SRCS
+    vscanf.cpp
+  HDRS
+    ../vscanf.h
+  DEPENDS
+    ${scanf_deps}
+)
+
 add_entrypoint_object(
   fgets
   SRCS
diff --git a/libc/src/stdio/fscanf.cpp b/libc/src/stdio/generic/fscanf.cpp
similarity index 100%
rename from libc/src/stdio/fscanf.cpp
rename to libc/src/stdio/generic/fscanf.cpp
diff --git a/libc/src/stdio/scanf.cpp b/libc/src/stdio/generic/scanf.cpp
similarity index 100%
rename from libc/src/stdio/scanf.cpp
rename to libc/src/stdio/generic/scanf.cpp
diff --git a/libc/src/stdio/vfscanf.cpp b/libc/src/stdio/generic/vfscanf.cpp
similarity index 100%
rename from libc/src/stdio/vfscanf.cpp
rename to libc/src/stdio/generic/vfscanf.cpp
diff --git a/libc/src/stdio/vscanf.cpp b/libc/src/stdio/generic/vscanf.cpp
similarity index 100%
rename from libc/src/stdio/vscanf.cpp
rename to libc/src/stdio/generic/vscanf.cpp
diff --git a/libc/src/stdio/scanf_core/CMakeLists.txt b/libc/src/stdio/scanf_core/CMakeLists.txt
index 014413ccaa8da..3de1e6a6eea37 100644
--- a/libc/src/stdio/scanf_core/CMakeLists.txt
+++ b/libc/src/stdio/scanf_core/CMakeLists.txt
@@ -16,6 +16,8 @@ if(LIBC_TARGET_OS_IS_GPU)
     libc.src.stdio.ungetc
     libc.src.stdio.ferror
   )
+elseif(LIBC_TARGET_OS_IS_BAREMETAL)
+  # There's no FILE* for baremetal.
 elseif(LLVM_LIBC_FULL_BUILD)
   list(APPEND file_deps
     libc.src.__support.File.file
@@ -54,17 +56,8 @@ add_header_library(
     libc.src.__support.CPP.string_view
 )
 
-if(NOT(TARGET libc.src.__support.File.file) AND LLVM_LIBC_FULL_BUILD AND
-  (NOT LIBC_TARGET_OS_IS_GPU))
-  # Not all platforms have a file implementation. If file is unvailable, and a
-  # full build is requested, then we must skip all file based scanf sections.
-  return()
-endif()
-
-add_object_library(
+add_header_library(
   scanf_main
-  SRCS
-    scanf_main.cpp
   HDRS
     scanf_main.h
   DEPENDS
@@ -87,14 +80,8 @@ add_header_library(
   ${use_system_file}
 )
 
-add_object_library(
+add_header_library(
   converter
-  SRCS
-    converter.cpp
-    string_converter.cpp
-    int_converter.cpp
-    float_converter.cpp
-    ptr_converter.cpp
   HDRS
     converter.h
     converter_utils.h
diff --git a/libc/src/stdio/scanf_core/converter.cpp b/libc/src/stdio/scanf_core/converter.cpp
index b1ee8cd1e74bb..fb234ce7864cf 100644
--- a/libc/src/stdio/scanf_core/converter.cpp
+++ b/libc/src/stdio/scanf_core/converter.cpp
@@ -26,78 +26,5 @@
 namespace LIBC_NAMESPACE_DECL {
 namespace scanf_core {
 
-int convert(Reader *reader, const FormatSection &to_conv) {
-  int ret_val = 0;
-  switch (to_conv.conv_name) {
-  case '%':
-    return raw_match(reader, "%");
-  case 's':
-    ret_val = raw_match(reader, " ");
-    if (ret_val != READ_OK)
-      return ret_val;
-    return convert_string(reader, to_conv);
-  case 'c':
-  case '[':
-    return convert_string(reader, to_conv);
-  case 'd':
-  case 'i':
-  case 'u':
-  case 'o':
-  case 'x':
-  case 'X':
-    ret_val = raw_match(reader, " ");
-    if (ret_val != READ_OK)
-      return ret_val;
-    return convert_int(reader, to_conv);
-#ifndef LIBC_COPT_SCANF_DISABLE_FLOAT
-  case 'f':
-  case 'F':
-  case 'e':
-  case 'E':
-  case 'a':
-  case 'A':
-  case 'g':
-  case 'G':
-    ret_val = raw_match(reader, " ");
-    if (ret_val != READ_OK)
-      return ret_val;
-    return convert_float(reader, to_conv);
-#endif // LIBC_COPT_SCANF_DISABLE_FLOAT
-  case 'n':
-    return convert_current_pos(reader, to_conv);
-  case 'p':
-    ret_val = raw_match(reader, " ");
-    if (ret_val != READ_OK)
-      return ret_val;
-    return convert_pointer(reader, to_conv);
-  default:
-    return raw_match(reader, to_conv.raw_string);
-  }
-  return -1;
-}
-
-// raw_string is assumed to have a positive size.
-int raw_match(Reader *reader, cpp::string_view raw_string) {
-  char cur_char = reader->getc();
-  int ret_val = READ_OK;
-  for (size_t i = 0; i < raw_string.size(); ++i) {
-    // Any space character matches any number of space characters.
-    if (internal::isspace(raw_string[i])) {
-      while (internal::isspace(cur_char)) {
-        cur_char = reader->getc();
-      }
-    } else {
-      if (raw_string[i] == cur_char) {
-        cur_char = reader->getc();
-      } else {
-        ret_val = MATCHING_FAILURE;
-        break;
-      }
-    }
-  }
-  reader->ungetc(cur_char);
-  return ret_val;
-}
-
 } // namespace scanf_core
 } // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdio/scanf_core/converter.h b/libc/src/stdio/scanf_core/converter.h
index 3f514eeb75bdf..3df43e9de1e25 100644
--- a/libc/src/stdio/scanf_core/converter.h
+++ b/libc/src/stdio/scanf_core/converter.h
@@ -10,10 +10,19 @@
 #define LLVM_LIBC_SRC_STDIO_SCANF_CORE_CONVERTER_H
 
 #include "src/__support/CPP/string_view.h"
+#include "src/__support/ctype_utils.h"
 #include "src/__support/macros/config.h"
 #include "src/stdio/scanf_core/core_structs.h"
 #include "src/stdio/scanf_core/reader.h"
 
+#ifndef LIBC_COPT_SCANF_DISABLE_FLOAT
+#include "src/stdio/scanf_core/float_converter.h"
+#endif // LIBC_COPT_SCANF_DISABLE_FLOAT
+#include "src/stdio/scanf_core/current_pos_converter.h"
+#include "src/stdio/scanf_core/int_converter.h"
+#include "src/stdio/scanf_core/ptr_converter.h"
+#include "src/stdio/scanf_core/string_converter.h"
+
 #include <stddef.h>
 
 namespace LIBC_NAMESPACE_DECL {
@@ -22,11 +31,81 @@ namespace scanf_core {
 // convert will call a conversion function to convert the FormatSection into
 // its string representation, and then that will write the result to the
 // reader.
-int convert(Reader *reader, const FormatSection &to_conv);
+template <typename T>
+int convert(Reader<T> *reader, const FormatSection &to_conv) {
+  int ret_val = 0;
+  switch (to_conv.conv_name) {
+  case '%':
+    return raw_match(reader, "%");
+  case 's':
+    ret_val = raw_match(reader, " ");
+    if (ret_val != READ_OK)
+      return ret_val;
+    return convert_string(reader, to_conv);
+  case 'c':
+  case '[':
+    return convert_string(reader, to_conv);
+  case 'd':
+  case 'i':
+  case 'u':
+  case 'o':
+  case 'x':
+  case 'X':
+    ret_val = raw_match(reader, " ");
+    if (ret_val != READ_OK)
+      return ret_val;
+    return convert_int(reader, to_conv);
+#ifndef LIBC_COPT_SCANF_DISABLE_FLOAT
+  case 'f':
+  case 'F':
+  case 'e':
+  case 'E':
+  case 'a':
+  case 'A':
+  case 'g':
+  case 'G':
+    ret_val = raw_match(reader, " ");
+    if (ret_val != READ_OK)
+      return ret_val;
+    return convert_float(reader, to_conv);
+#endif // LIBC_COPT_SCANF_DISABLE_FLOAT
+  case 'n':
+    return convert_current_pos(reader, to_conv);
+  case 'p':
+    ret_val = raw_match(reader, " ");
+    if (ret_val != READ_OK)
+      return ret_val;
+    return convert_pointer(reader, to_conv);
+  default:
+    return raw_match(reader, to_conv.raw_string);
+  }
+  return -1;
+}
 
 // raw_match takes a raw string and matches it to the characters obtained from
 // the reader.
-int raw_match(Reader *reader, cpp::string_view raw_string);
+template <typename T>
+int raw_match(Reader<T> *reader, cpp::string_view raw_string) {
+  char cur_char = reader->getc();
+  int ret_val = READ_OK;
+  for (size_t i = 0; i < raw_string.size(); ++i) {
+    // Any space character matches any number of space characters.
+    if (internal::isspace(raw_string[i])) {
+      while (internal::isspace(cur_char)) {
+        cur_char = reader->getc();
+      }
+    } else {
+      if (raw_string[i] == cur_char) {
+        cur_char = reader->getc();
+      } else {
+        ret_val = MATCHING_FAILURE;
+        break;
+      }
+    }
+  }
+  reader->ungetc(cur_char);
+  return ret_val;
+}
 
 } // namespace scanf_core
 } // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdio/scanf_core/current_pos_converter.h b/libc/src/stdio/scanf_core/current_pos_converter.h
index 8af1cc0ca0c27..8708490c82d3e 100644
--- a/libc/src/stdio/scanf_core/current_pos_converter.h
+++ b/libc/src/stdio/scanf_core/current_pos_converter.h
@@ -19,7 +19,8 @@
 namespace LIBC_NAMESPACE_DECL {
 namespace scanf_core {
 
-LIBC_INLINE int convert_current_pos(Reader *reader,
+template <typename T>
+LIBC_INLINE int convert_current_pos(Reader<T> *reader,
                                     const FormatSection &to_conv) {
   write_int_with_length(reader->chars_read(), to_conv);
   return READ_OK;
diff --git a/libc/src/stdio/scanf_core/float_converter.cpp b/libc/src/stdio/scanf_core/float_converter.cpp
deleted file mode 100644
index 9c714d0727214..0000000000000
--- a/libc/src/stdio/scanf_core/float_converter.cpp
+++ /dev/null
@@ -1,229 +0,0 @@
-//===-- Int type specifier converters for scanf -----------------*- C++ -*-===//
-//
-// 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/stdio/scanf_core/float_converter.h"
-
-#include "src/__support/CPP/limits.h"
-#include "src/__support/char_vector.h"
-#include "src/__support/ctype_utils.h"
-#include "src/__support/macros/config.h"
-#include "src/stdio/scanf_core/converter_utils.h"
-#include "src/stdio/scanf_core/core_structs.h"
-#include "src/stdio/scanf_core/reader.h"
-
-#include <stddef.h>
-
-namespace LIBC_NAMESPACE_DECL {
-namespace scanf_core {
-
-// All of the floating point conversions are the same for scanf, every name will
-// accept every style.
-int convert_float(Reader *reader, const FormatSection &to_conv) {
-  // %a/A/e/E/f/F/g/G "Matches an optionally signed floating-point number,
-  // infinity, or NaN, whose format is the same as expected for the subject
-  // sequence of the strtod function. The corresponding argument shall be a
-  // pointer to floating."
-
-  CharVector out_str = CharVector();
-  bool is_number = false;
-
-  size_t max_width = cpp::numeric_limits<size_t>::max();
-  if (to_conv.max_width > 0) {
-    max_width = to_conv.max_width;
-  }
-
-  char cur_char = reader->getc();
-  // Handle the sign.
-  if (cur_char == '+' || cur_char == '-') {
-    if (!...
[truncated]

@petrhosek
Copy link
Member Author

This PR currently also includes support for scanf on baremetal since that was the original motivation but I could break that part out into a separate PR to make it smaller.

@petrhosek
Copy link
Member Author

@michaelrj-google Do you have any opinion on keeping Reader and ReadBuffer (and its subclasses) separate vs merging them together? I'm leaning towards merging them together to simplify the code even further.

Verified

This commit was signed with the committer’s verified signature. The key has expired.
pganssle Paul Ganssle
This allows specializing the implementation for different targets
without including unnecessary logic and is similar to llvm#111559 which
did the same for printf Writer interface.
@petrhosek petrhosek force-pushed the libc-templatize-scanf branch from 5c75b13 to 2610f9a Compare March 12, 2025 22:39
petrhosek added a commit to petrhosek/llvm-project that referenced this pull request Mar 12, 2025

Verified

This commit was signed with the committer’s verified signature. The key has expired.
pganssle Paul Ganssle
This uses the templatized scanf Reader interface introduced in llvm#131037.
@petrhosek
Copy link
Member Author

This PR currently also includes support for scanf on baremetal since that was the original motivation but I could break that part out into a separate PR to make it smaller.

I moved the baremetal implementation of scanf to #131043.

@@ -26,78 +26,5 @@
namespace LIBC_NAMESPACE_DECL {
Copy link
Contributor

Choose a reason for hiding this comment

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

this file can be deleted.

Copy link
Member Author

Choose a reason for hiding this comment

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

Done.

class Reader {
ReadBuffer *rb;
void *input_stream = nullptr;
// TODO: We should be able to fold ReadBuffer into Reader.
Copy link
Contributor

Choose a reason for hiding this comment

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

How about this:

template <typename Derived> class Reader {
  size_t cur_chars_read = 0;

public:
  // This returns the next character from the input and advances it by one
  // character. When it hits the end of the string or file it returns '\0' to
  // signal to stop parsing.
  LIBC_INLINE char getc() {
    ++cur_chars_read;
    return static_cast<Derived *>(this)->getc();
  }

  // This moves the input back by one character, placing c into the buffer if
  // this is a file reader, else c is ignored.
  LIBC_INLINE void ungetc(char c) {
    --cur_chars_read;
    static_cast<Derived *>(this)->ungetc(c);
  }

  LIBC_INLINE size_t chars_read() { return cur_chars_read; }
};

class StringReader : public Reader<StringReader> {
  const char *buffer;
  [[maybe_unused]] size_t buff_len;
  size_t buff_cur = 0;

public:
  LIBC_INLINE StringReader(const char *buffer, size_t buff_len)
      : buffer(buffer), buff_len(buff_len) {}

  LIBC_INLINE char getc() {
    char output = buffer[buff_cur];
    ++buff_cur;
    return output;
  }
  LIBC_INLINE void ungetc(int) {
    if (buff_cur > 0) {
      // While technically c should be written back to the buffer, in scanf we
      // always write the character that was already there. Additionally, the
      // buffer is most likely to contain a string that isn't part of a file,
      // which may not be writable.
      --buff_cur;
    }
  }
};

I'm fine with merging them in this way since the subclass already needs to track state, so making it fully static wouldn't work.

Copy link
Member Author

Choose a reason for hiding this comment

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

Done.

Comment on lines 94 to 107
class StreamBuffer : public ReadBuffer<StreamBuffer> {
::FILE *stream;

public:
LIBC_INLINE StreamBuffer(::FILE *stream) : stream(stream) {}

LIBC_INLINE char getc() {
return static_cast<char>(internal::getc(static_cast<FILE *>(stream)));
}
LIBC_INLINE void ungetc(int c) {
internal::ungetc(c, static_cast<FILE *>(stream));
}
};

Copy link
Contributor

Choose a reason for hiding this comment

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

I'd like to also add a dynamic dispatch reader that stores a union of StringReader and StreamReader so to make that simpler I'd like to move each reader subclass into its own file.

Verified

This commit was signed with the committer’s verified signature. The key has expired.
pganssle Paul Ganssle
Copy link

github-actions bot commented Mar 13, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

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.

LGTM

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
@petrhosek petrhosek merged commit 1fbfef9 into llvm:main Mar 18, 2025
16 checks passed
@llvm-ci
Copy link
Collaborator

llvm-ci commented Mar 18, 2025

LLVM Buildbot has detected a new failure on builder openmp-offload-amdgpu-runtime-2 running on rocm-worker-hw-02 while building libc at step 5 "compile-openmp".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/10/builds/1542

Here is the relevant piece of the build log for the reference
Step 5 (compile-openmp) failure: build (failure)
...
0.502 [173/130/390] Building CXX object libc/src/stdlib/CMakeFiles/libc.src.stdlib.atexit.dir/atexit.cpp.o
0.503 [172/130/391] Building CXX object libc/src/stdio/gpu/CMakeFiles/libc.src.stdio.gpu.getc.dir/getc.cpp.o
0.504 [171/130/392] Building CXX object libc/src/stdio/gpu/CMakeFiles/libc.src.stdio.gpu.fgets.dir/fgets.cpp.o
0.508 [170/130/393] Building CXX object libc/src/stdlib/gpu/CMakeFiles/libc.src.stdlib.gpu.system.dir/system.cpp.o
0.509 [169/130/394] Building CXX object libc/src/stdio/gpu/CMakeFiles/libc.src.stdio.gpu.fread.dir/fread.cpp.o
0.512 [168/130/395] Building CXX object libc/src/stdio/gpu/CMakeFiles/libc.src.stdio.gpu.ungetc.dir/ungetc.cpp.o
0.517 [167/130/396] Building CXX object libc/src/stdio/gpu/CMakeFiles/libc.src.stdio.gpu.getchar.dir/getchar.cpp.o
0.528 [166/130/397] Building CXX object libc/src/stdio/gpu/CMakeFiles/libc.src.stdio.gpu.putchar.dir/putchar.cpp.o
0.537 [165/130/398] Building CXX object libc/src/assert/gpu/CMakeFiles/libc.src.assert.gpu.__assert_fail.dir/__assert_fail.cpp.o
0.540 [164/130/399] Building CXX object libc/src/stdio/CMakeFiles/libc.src.stdio.fscanf.dir/fscanf.cpp.o
FAILED: libc/src/stdio/CMakeFiles/libc.src.stdio.fscanf.dir/fscanf.cpp.o 
/home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.build/./bin/clang++ --target=amdgcn-amd-amdhsa -DLIBC_NAMESPACE=__llvm_libc_21_0_0_git -D__LIBC_USE_FLOAT16_CONVERSION -I/home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/libc -isystem /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.build/include/amdgcn-amd-amdhsa -O3 -DNDEBUG --target=amdgcn-amd-amdhsa -DLIBC_QSORT_IMPL=LIBC_QSORT_QUICK_SORT -DLIBC_ADD_NULL_CHECKS "-DLIBC_MATH=(LIBC_MATH_SKIP_ACCURATE_PASS | LIBC_MATH_SMALL_TABLES | LIBC_MATH_NO_ERRNO | LIBC_MATH_NO_EXCEPT)" -fpie -DLIBC_FULL_BUILD -nostdlibinc -ffixed-point -fno-exceptions -fno-lax-vector-conversions -fno-unwind-tables -fno-asynchronous-unwind-tables -fno-rtti -ftrivial-auto-var-init=pattern -fno-omit-frame-pointer -Wall -Wextra -Werror -Wconversion -Wno-sign-conversion -Wdeprecated -Wno-c99-extensions -Wno-gnu-imaginary-constant -Wno-pedantic -Wimplicit-fallthrough -Wwrite-strings -Wextra-semi -Wnewline-eof -Wnonportable-system-include-path -Wstrict-prototypes -Wthread-safety -Wglobal-constructors -nogpulib -fvisibility=hidden -fconvergent-functions -flto -Wno-multi-gpu -Xclang -mcode-object-version=none -DLIBC_COPT_PUBLIC_PACKAGING -UNDEBUG -DLIBC_COPT_SCANF_DISABLE_FLOAT -DLIBC_COPT_SCANF_DISABLE_INDEX_MODE -MD -MT libc/src/stdio/CMakeFiles/libc.src.stdio.fscanf.dir/fscanf.cpp.o -MF libc/src/stdio/CMakeFiles/libc.src.stdio.fscanf.dir/fscanf.cpp.o.d -o libc/src/stdio/CMakeFiles/libc.src.stdio.fscanf.dir/fscanf.cpp.o -c /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/libc/src/stdio/fscanf.cpp
In file included from /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/libc/src/stdio/fscanf.cpp:14:
/home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/libc/src/stdio/scanf_core/vfscanf_internal.h:41:42: error: no member named 'getc' in namespace '__llvm_libc_21_0_0_git'; did you mean simply 'getc'?
   41 | LIBC_INLINE int getc(::FILE *f) { return LIBC_NAMESPACE::getc(f); }
      |                                          ^~~~~~~~~~~~~~~~~~~~
      |                                          getc
<command line>:1:24: note: expanded from macro 'LIBC_NAMESPACE'
    1 | #define LIBC_NAMESPACE __llvm_libc_21_0_0_git
      |                        ^
/home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/libc/src/stdio/scanf_core/vfscanf_internal.h:41:17: note: 'getc' declared here
   41 | LIBC_INLINE int getc(::FILE *f) { return LIBC_NAMESPACE::getc(f); }
      |                 ^
/home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/libc/src/stdio/scanf_core/vfscanf_internal.h:43:45: error: no member named 'ungetc' in namespace '__llvm_libc_21_0_0_git'; did you mean simply 'ungetc'?
   43 | LIBC_INLINE void ungetc(int c, ::FILE *f) { LIBC_NAMESPACE::ungetc(c, f); }
      |                                             ^~~~~~~~~~~~~~~~~~~~~~
      |                                             ungetc
<command line>:1:24: note: expanded from macro 'LIBC_NAMESPACE'
    1 | #define LIBC_NAMESPACE __llvm_libc_21_0_0_git
      |                        ^
/home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/libc/src/stdio/scanf_core/vfscanf_internal.h:43:18: note: 'ungetc' declared here
   43 | LIBC_INLINE void ungetc(int c, ::FILE *f) { LIBC_NAMESPACE::ungetc(c, f); }
      |                  ^
2 errors generated.
0.542 [164/129/400] Building CXX object libc/src/stdio/CMakeFiles/libc.src.stdio.vfscanf.dir/vfscanf.cpp.o
FAILED: libc/src/stdio/CMakeFiles/libc.src.stdio.vfscanf.dir/vfscanf.cpp.o 
/home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.build/./bin/clang++ --target=amdgcn-amd-amdhsa -DLIBC_NAMESPACE=__llvm_libc_21_0_0_git -D__LIBC_USE_FLOAT16_CONVERSION -I/home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/libc -isystem /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.build/include/amdgcn-amd-amdhsa -O3 -DNDEBUG --target=amdgcn-amd-amdhsa -DLIBC_QSORT_IMPL=LIBC_QSORT_QUICK_SORT -DLIBC_ADD_NULL_CHECKS "-DLIBC_MATH=(LIBC_MATH_SKIP_ACCURATE_PASS | LIBC_MATH_SMALL_TABLES | LIBC_MATH_NO_ERRNO | LIBC_MATH_NO_EXCEPT)" -fpie -DLIBC_FULL_BUILD -nostdlibinc -ffixed-point -fno-exceptions -fno-lax-vector-conversions -fno-unwind-tables -fno-asynchronous-unwind-tables -fno-rtti -ftrivial-auto-var-init=pattern -fno-omit-frame-pointer -Wall -Wextra -Werror -Wconversion -Wno-sign-conversion -Wdeprecated -Wno-c99-extensions -Wno-gnu-imaginary-constant -Wno-pedantic -Wimplicit-fallthrough -Wwrite-strings -Wextra-semi -Wnewline-eof -Wnonportable-system-include-path -Wstrict-prototypes -Wthread-safety -Wglobal-constructors -nogpulib -fvisibility=hidden -fconvergent-functions -flto -Wno-multi-gpu -Xclang -mcode-object-version=none -DLIBC_COPT_PUBLIC_PACKAGING -UNDEBUG -DLIBC_COPT_SCANF_DISABLE_FLOAT -DLIBC_COPT_SCANF_DISABLE_INDEX_MODE -MD -MT libc/src/stdio/CMakeFiles/libc.src.stdio.vfscanf.dir/vfscanf.cpp.o -MF libc/src/stdio/CMakeFiles/libc.src.stdio.vfscanf.dir/vfscanf.cpp.o.d -o libc/src/stdio/CMakeFiles/libc.src.stdio.vfscanf.dir/vfscanf.cpp.o -c /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/libc/src/stdio/vfscanf.cpp
In file included from /home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/libc/src/stdio/vfscanf.cpp:14:
/home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/libc/src/stdio/scanf_core/vfscanf_internal.h:41:42: error: no member named 'getc' in namespace '__llvm_libc_21_0_0_git'; did you mean simply 'getc'?
   41 | LIBC_INLINE int getc(::FILE *f) { return LIBC_NAMESPACE::getc(f); }
      |                                          ^~~~~~~~~~~~~~~~~~~~
      |                                          getc
<command line>:1:24: note: expanded from macro 'LIBC_NAMESPACE'
    1 | #define LIBC_NAMESPACE __llvm_libc_21_0_0_git
      |                        ^
/home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/libc/src/stdio/scanf_core/vfscanf_internal.h:41:17: note: 'getc' declared here
   41 | LIBC_INLINE int getc(::FILE *f) { return LIBC_NAMESPACE::getc(f); }
      |                 ^
/home/botworker/builds/openmp-offload-amdgpu-runtime-2/llvm.src/libc/src/stdio/scanf_core/vfscanf_internal.h:43:45: error: no member named 'ungetc' in namespace '__llvm_libc_21_0_0_git'; did you mean simply 'ungetc'?

@llvm-ci
Copy link
Collaborator

llvm-ci commented Mar 18, 2025

LLVM Buildbot has detected a new failure on builder openmp-offload-libc-amdgpu-runtime running on omp-vega20-1 while building libc at step 5 "compile-openmp".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/73/builds/14781

Here is the relevant piece of the build log for the reference
Step 5 (compile-openmp) failure: build (failure)
...
0.948 [360/34/299] Building CXX object libc/src/stdio/gpu/CMakeFiles/libc.src.stdio.gpu.fgets.dir/fgets.cpp.o
0.953 [359/34/300] Building CXX object libc/src/stdio/gpu/CMakeFiles/libc.src.stdio.gpu.fread.dir/fread.cpp.o
0.967 [358/34/301] Building CXX object libc/src/stdio/gpu/CMakeFiles/libc.src.stdio.gpu.getchar.dir/getchar.cpp.o
0.979 [357/34/302] Building CXX object libc/src/stdio/gpu/CMakeFiles/libc.src.stdio.gpu.fgetc.dir/fgetc.cpp.o
0.980 [356/34/303] Building CXX object libc/src/stdio/gpu/CMakeFiles/libc.src.stdio.gpu.remove.dir/remove.cpp.o
0.982 [355/34/304] Building CXX object libc/src/stdio/gpu/CMakeFiles/libc.src.stdio.gpu.getc.dir/getc.cpp.o
0.993 [354/34/305] Building CXX object libc/src/stdio/gpu/CMakeFiles/libc.src.stdio.gpu.rename.dir/rename.cpp.o
1.009 [353/34/306] Building CXX object libc/src/stdio/gpu/CMakeFiles/libc.src.stdio.gpu.putchar.dir/putchar.cpp.o
1.011 [352/34/307] Building CXX object libc/src/stdio/gpu/CMakeFiles/libc.src.stdio.gpu.fclose.dir/fclose.cpp.o
1.022 [351/34/308] Building CXX object libc/src/stdio/CMakeFiles/libc.src.stdio.fscanf.dir/fscanf.cpp.o
FAILED: libc/src/stdio/CMakeFiles/libc.src.stdio.fscanf.dir/fscanf.cpp.o 
/home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/./bin/clang++ --target=amdgcn-amd-amdhsa -DLIBC_NAMESPACE=__llvm_libc_21_0_0_git -D__LIBC_USE_FLOAT16_CONVERSION -I/home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.src/libc -isystem /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/include/amdgcn-amd-amdhsa -O3 -DNDEBUG --target=amdgcn-amd-amdhsa -DLIBC_QSORT_IMPL=LIBC_QSORT_QUICK_SORT -DLIBC_ADD_NULL_CHECKS "-DLIBC_MATH=(LIBC_MATH_SKIP_ACCURATE_PASS | LIBC_MATH_SMALL_TABLES | LIBC_MATH_NO_ERRNO | LIBC_MATH_NO_EXCEPT)" -fpie -DLIBC_FULL_BUILD -nostdlibinc -ffixed-point -fno-exceptions -fno-lax-vector-conversions -fno-unwind-tables -fno-asynchronous-unwind-tables -fno-rtti -ftrivial-auto-var-init=pattern -fno-omit-frame-pointer -Wall -Wextra -Werror -Wconversion -Wno-sign-conversion -Wdeprecated -Wno-c99-extensions -Wno-gnu-imaginary-constant -Wno-pedantic -Wimplicit-fallthrough -Wwrite-strings -Wextra-semi -Wnewline-eof -Wnonportable-system-include-path -Wstrict-prototypes -Wthread-safety -Wglobal-constructors -nogpulib -fvisibility=hidden -fconvergent-functions -flto -Wno-multi-gpu -Xclang -mcode-object-version=none -DLIBC_COPT_PUBLIC_PACKAGING -UNDEBUG -DLIBC_COPT_SCANF_DISABLE_FLOAT -DLIBC_COPT_SCANF_DISABLE_INDEX_MODE -MD -MT libc/src/stdio/CMakeFiles/libc.src.stdio.fscanf.dir/fscanf.cpp.o -MF libc/src/stdio/CMakeFiles/libc.src.stdio.fscanf.dir/fscanf.cpp.o.d -o libc/src/stdio/CMakeFiles/libc.src.stdio.fscanf.dir/fscanf.cpp.o -c /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.src/libc/src/stdio/fscanf.cpp
In file included from /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.src/libc/src/stdio/fscanf.cpp:14:
/home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.src/libc/src/stdio/scanf_core/vfscanf_internal.h:41:42: error: no member named 'getc' in namespace '__llvm_libc_21_0_0_git'; did you mean simply 'getc'?
   41 | LIBC_INLINE int getc(::FILE *f) { return LIBC_NAMESPACE::getc(f); }
      |                                          ^~~~~~~~~~~~~~~~~~~~
      |                                          getc
<command line>:1:24: note: expanded from macro 'LIBC_NAMESPACE'
    1 | #define LIBC_NAMESPACE __llvm_libc_21_0_0_git
      |                        ^
/home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.src/libc/src/stdio/scanf_core/vfscanf_internal.h:41:17: note: 'getc' declared here
   41 | LIBC_INLINE int getc(::FILE *f) { return LIBC_NAMESPACE::getc(f); }
      |                 ^
/home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.src/libc/src/stdio/scanf_core/vfscanf_internal.h:43:45: error: no member named 'ungetc' in namespace '__llvm_libc_21_0_0_git'; did you mean simply 'ungetc'?
   43 | LIBC_INLINE void ungetc(int c, ::FILE *f) { LIBC_NAMESPACE::ungetc(c, f); }
      |                                             ^~~~~~~~~~~~~~~~~~~~~~
      |                                             ungetc
<command line>:1:24: note: expanded from macro 'LIBC_NAMESPACE'
    1 | #define LIBC_NAMESPACE __llvm_libc_21_0_0_git
      |                        ^
/home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.src/libc/src/stdio/scanf_core/vfscanf_internal.h:43:18: note: 'ungetc' declared here
   43 | LIBC_INLINE void ungetc(int c, ::FILE *f) { LIBC_NAMESPACE::ungetc(c, f); }
      |                  ^
2 errors generated.
1.023 [351/33/309] Building CXX object libc/src/stdio/CMakeFiles/libc.src.stdio.vscanf.dir/vscanf.cpp.o
FAILED: libc/src/stdio/CMakeFiles/libc.src.stdio.vscanf.dir/vscanf.cpp.o 
/home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/./bin/clang++ --target=amdgcn-amd-amdhsa -DLIBC_NAMESPACE=__llvm_libc_21_0_0_git -D__LIBC_USE_FLOAT16_CONVERSION -I/home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.src/libc -isystem /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/include/amdgcn-amd-amdhsa -O3 -DNDEBUG --target=amdgcn-amd-amdhsa -DLIBC_QSORT_IMPL=LIBC_QSORT_QUICK_SORT -DLIBC_ADD_NULL_CHECKS "-DLIBC_MATH=(LIBC_MATH_SKIP_ACCURATE_PASS | LIBC_MATH_SMALL_TABLES | LIBC_MATH_NO_ERRNO | LIBC_MATH_NO_EXCEPT)" -fpie -DLIBC_FULL_BUILD -nostdlibinc -ffixed-point -fno-exceptions -fno-lax-vector-conversions -fno-unwind-tables -fno-asynchronous-unwind-tables -fno-rtti -ftrivial-auto-var-init=pattern -fno-omit-frame-pointer -Wall -Wextra -Werror -Wconversion -Wno-sign-conversion -Wdeprecated -Wno-c99-extensions -Wno-gnu-imaginary-constant -Wno-pedantic -Wimplicit-fallthrough -Wwrite-strings -Wextra-semi -Wnewline-eof -Wnonportable-system-include-path -Wstrict-prototypes -Wthread-safety -Wglobal-constructors -nogpulib -fvisibility=hidden -fconvergent-functions -flto -Wno-multi-gpu -Xclang -mcode-object-version=none -DLIBC_COPT_PUBLIC_PACKAGING -UNDEBUG -DLIBC_COPT_SCANF_DISABLE_FLOAT -DLIBC_COPT_SCANF_DISABLE_INDEX_MODE -MD -MT libc/src/stdio/CMakeFiles/libc.src.stdio.vscanf.dir/vscanf.cpp.o -MF libc/src/stdio/CMakeFiles/libc.src.stdio.vscanf.dir/vscanf.cpp.o.d -o libc/src/stdio/CMakeFiles/libc.src.stdio.vscanf.dir/vscanf.cpp.o -c /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.src/libc/src/stdio/vscanf.cpp
In file included from /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.src/libc/src/stdio/vscanf.cpp:14:
/home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.src/libc/src/stdio/scanf_core/vfscanf_internal.h:41:42: error: no member named 'getc' in namespace '__llvm_libc_21_0_0_git'; did you mean simply 'getc'?
   41 | LIBC_INLINE int getc(::FILE *f) { return LIBC_NAMESPACE::getc(f); }
      |                                          ^~~~~~~~~~~~~~~~~~~~
      |                                          getc
<command line>:1:24: note: expanded from macro 'LIBC_NAMESPACE'
    1 | #define LIBC_NAMESPACE __llvm_libc_21_0_0_git
      |                        ^
/home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.src/libc/src/stdio/scanf_core/vfscanf_internal.h:41:17: note: 'getc' declared here
   41 | LIBC_INLINE int getc(::FILE *f) { return LIBC_NAMESPACE::getc(f); }
      |                 ^
/home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.src/libc/src/stdio/scanf_core/vfscanf_internal.h:43:45: error: no member named 'ungetc' in namespace '__llvm_libc_21_0_0_git'; did you mean simply 'ungetc'?

petrhosek added a commit that referenced this pull request Mar 20, 2025
This uses the templatized scanf Reader interface introduced in #131037.
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.

None yet

4 participants