ronantakizawa/codereview-bench huggingface dataset:
Repository: llvm/llvm-project
File: clang/test/Modules/config_macros.m (Objective-C)

Code before:

//--- config.h

#ifdef WANT_FOO
int* foo(void);
#endif

#ifdef WANT_BAR
char *bar(void);
#endif

//--- config_error.h

struct my_thing {
  char buf[SOME_VALUE];
};

//--- config.m

@import config;

int *test_foo(void) {
  return foo();
}

char *test_bar(void) {
  return bar(); // expected-error{{call to undeclared function 'bar'; ISO C99 and later do not support implicit function declarations}} \
                // expected-error{{incompatible integer to pointer conversion}}
}

#undef WANT_FOO // expected-note{{macro was #undef'd here}}
@import config; // expected-warning{{#undef of configuration macro 'WANT_FOO' has no effect on the import of 'config'; pass '-UWANT_FOO' on the command line to configure the module}}

#define WANT_FOO 2 // expected-note{{macro was defined here}}
@import config; // expected-warning{{definition of configuration macro 'WANT_FOO' has no effect on the import of 'config'; pass '-DWANT_FOO=...' on the command line to configure the module}}

#undef WANT_FOO
#define WANT_FOO 1
@import config; // okay

#define WANT_BAR 1 // expected-note{{macro was defined here}}
@import config; // expected-warning{{definition of configuration macro 'WANT_BAR' has no effect on the import of 'config'; pass '-DWANT_BAR=...' on the command line to configure the module}}

//--- config_error.m

#ifdef TEST_ERROR
#define SOME_VALUE 5 // expected-note{{macro was defined here}}
@import config_error; // expected-error{{could not build module}} \
                      // expected-warning{{definition of configuration macro 'SOME_VALUE' has no effect on the import of 'config_error';}}
#endif


Review comment (suggestion):
Don't think it is worth verifying in the test but we have a diagnostic
```
error: use of undeclared identifier 'SOME_VALUE'
```
which is still useful when we have no corresponding macro defined anywhere.

Code after:
//--- module.modulemap

module config {
  header "config.h"
  config_macros [exhaustive] WANT_FOO, WANT_BAR
}

module config_error {
  header "config_error.h"
  config_macros SOME_VALUE
}

//--- config.h

#ifdef WANT_FOO
int* foo(void);
#endif

#ifdef WANT_BAR
char *bar(void);
#endif

//--- config_error.h

struct my_thing {
  char buf[SOME_VALUE];
};

//--- config.m

@import config;

int *test_foo(void) {
  return foo();
}

char *test_bar(void) {
  return bar(); // expected-error{{call to undeclared function 'bar'; ISO C99 and later do not support implicit function declarations}} \
                // expected-error{{incompatible integer to pointer conversion}}
}

#undef WANT_FOO // expected-note{{macro was #undef'd here}}
@import config; // expected-warning{{#undef of configuration macro 'WANT_FOO' has no effect on the import of 'config'; pass '-UWANT_FOO' on the command line to configure the module}}

#define WANT_FOO 2 // expected-note{{macro was defined here}}
@import config; // expected-warning{{definition of configuration macro 'WANT_FOO' has no effect on the import of 'config'; pass '-DWANT_FOO=...' on the command line to configure the module}}

#undef WANT_FOO
#define WANT_FOO 1
@import config; // okay
Repository: llvm/llvm-project
File: llvm/test/MC/ELF/prefalign.s (Assembly)

Code before:
// RUN: llvm-mc -filetype=asm -triple x86_64-pc-linux-gnu %s -o - | FileCheck --check-prefix=ASM %s
// RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o - | llvm-readelf -SW - | FileCheck --check-prefix=OBJ %s

// Minimum alignment >= preferred alignment, no effect on sh_addralign.
// ASM: .section .text.f1lt
// ASM: .p2align 2
// ASM: .prefalign 2 
// OBJ: .text.f1lt        PROGBITS        0000000000000000 000040 000003 00  AX  0   0  4
.section .text.f1lt,"ax",@progbits
.p2align 2
.prefalign 2
.rept 3
nop
.endr

// ASM: .section .text.f1eq
// ASM: .p2align 2
// ASM: .prefalign 2 
// OBJ: .text.f1eq        PROGBITS        0000000000000000 000044 000004 00  AX  0   0  4
.section .text.f1eq,"ax",@progbits
.p2align 2
.prefalign 2
.rept 4
nop
.endr


Review comment (suggestion):
`llvm-mc -filetype=asm -triple x86_64-pc-linux-gnu %s -o -` => `llvm-mc -triple x86_64 %s`

Code after:
// RUN: llvm-mc -triple x86_64 %s -o - | FileCheck --check-prefix=ASM %s
// RUN: llvm-mc -filetype=obj -triple x86_64 %s -o - | llvm-readelf -SW - | FileCheck --check-prefix=OBJ %s

// Minimum alignment >= preferred alignment, no effect on sh_addralign.
// ASM: .section .text.f1lt
// ASM: .p2align 2
// ASM: .prefalign 2 
// OBJ: .text.f1lt        PROGBITS        0000000000000000 000040 000003 00  AX  0   0  4
.section .text.f1lt,"ax",@progbits
.p2align 2
.prefalign 2
.rept 3
nop
.endr

// ASM: .section .text.f1eq
// ASM: .p2align 2
// ASM: .prefalign 2 
// OBJ: .text.f1eq        PROGBITS        0000000000000000 000044 000004 00  AX  0   0  4
.section .text.f1eq,"ax",@progbits
.p2align 2
.prefalign 2
.rept 4
nop
.endr
Repository: llvm/llvm-project
File: llvm/include/llvm/IR/PatternMatch.h (C/C++)

Code before:

template <typename T>
inline AllowFmf_match<T, FastMathFlags::ApproxFunc>
m_ApproxFunc(const T &SubPattern) {
  return SubPattern;
}

template <typename T>
inline AllowFmf_match<T, FastMathFlags::NoNaNs> m_NoNaNs(const T &SubPattern) {
  return SubPattern;
}

template <typename T>
inline AllowFmf_match<T, FastMathFlags::NoInfs> m_NoInfs(const T &SubPattern) {
  return SubPattern;
}

template <typename T>
inline AllowFmf_match<T, FastMathFlags::NoSignedZeros>
m_NoSignedZeros(const T &SubPattern) {
  return SubPattern;
}

template <typename T>
inline AllowFmf_match<T, FastMathFlags::AllFlagsMask>
m_IsFast(const T &SubPattern) {
  return SubPattern;
}

template <typename Class> struct class_match {
  template <typename ITy> bool match(ITy *V) const { return isa<Class>(V); }
};

/// Match an arbitrary value and ignore it.
inline class_match<Value> m_Value() { return class_match<Value>(); }

/// Match an arbitrary unary operation and ignore it.
inline class_match<UnaryOperator> m_UnOp() {
  return class_match<UnaryOperator>();
}

/// Match an arbitrary binary operation and ignore it.
inline class_match<BinaryOperator> m_BinOp() {
  return class_match<BinaryOperator>();
}

/// Matches any compare instruction and ignore it.
inline class_match<CmpInst> m_Cmp() { return class_match<CmpInst>(); }

struct undef_match {
  static bool check(const Value *V) {

Review comment (suggestion):
I don't think we should have a matcher for `fast`, since checking all the flags is heavily discouraged.

Code after:
}

template <typename Class> struct class_match {
  template <typename ITy> bool match(ITy *V) const { return isa<Class>(V); }
};

/// Match an arbitrary value and ignore it.
inline class_match<Value> m_Value() { return class_match<Value>(); }

/// Match an arbitrary unary operation and ignore it.
inline class_match<UnaryOperator> m_UnOp() {
  return class_match<UnaryOperator>();
}

/// Match an arbitrary binary operation and ignore it.
inline class_match<BinaryOperator> m_BinOp() {
  return class_match<BinaryOperator>();
}

/// Matches any compare instruction and ignore it.
inline class_match<CmpInst> m_Cmp() { return class_match<CmpInst>(); }

struct undef_match {
  static bool check(const Value *V) {
    if (isa<UndefValue>(V))
      return true;

    const auto *CA = dyn_cast<ConstantAggregate>(V);
    if (!CA)
      return false;

    SmallPtrSet<const ConstantAggregate *, 8> Seen;
    SmallVector<const ConstantAggregate *, 8> Worklist;

    // Either UndefValue, PoisonValue, or an aggregate that only contains
    // these is accepted by matcher.
    // CheckValue returns false if CA cannot satisfy this constraint.
    auto CheckValue = [&](const ConstantAggregate *CA) {
      for (const Value *Op : CA->operand_values()) {
        if (isa<UndefValue>(Op))
          continue;

        const auto *CA = dyn_cast<ConstantAggregate>(Op);
        if (!CA)
          return false;
        if (Seen.insert(CA).second)
          Worklist.emplace_back(CA);
      }

      return true;
    };
Repository: llvm/llvm-project
File: llvm/include/llvm/IR/PatternMatch.h (C/C++)

Code before:
}

template <typename Pattern> bool match(ArrayRef<int> Mask, const Pattern &P) {
  return P.match(Mask);
}

template <typename SubPattern_t> struct OneUse_match {
  SubPattern_t SubPattern;

  OneUse_match(const SubPattern_t &SP) : SubPattern(SP) {}

  template <typename OpTy> bool match(OpTy *V) const {
    return V->hasOneUse() && SubPattern.match(V);
  }
};

template <typename T> inline OneUse_match<T> m_OneUse(const T &SubPattern) {
  return SubPattern;
}

template <typename SubPattern_t, int Flag> struct AllowFmf_match {
  SubPattern_t SubPattern;
  FastMathFlags FMF;

  AllowFmf_match(const SubPattern_t &SP) : SubPattern(SP) {
    if (Flag == FastMathFlags::AllowReassoc)
      FMF.setAllowReassoc();
    if (Flag == FastMathFlags::AllowReciprocal)
      FMF.setAllowReciprocal();
    if (Flag == FastMathFlags::AllowContract)
      FMF.setAllowContract();
    if (Flag == FastMathFlags::ApproxFunc)
      FMF.setApproxFunc();
    if (Flag == FastMathFlags::NoNaNs)
      FMF.setNoNaNs();
    if (Flag == FastMathFlags::NoInfs)
      FMF.setNoInfs();
    if (Flag == FastMathFlags::NoSignedZeros)
      FMF.setNoSignedZeros();
  }

  template <typename OpTy> bool match(OpTy *V) const {
    auto *I = dyn_cast<FPMathOperator>(V);
    return I && ((I->getFastMathFlags() & FMF) == FMF) && SubPattern.match(I);
  }
};

template <typename T>
inline AllowFmf_match<T, FastMathFlags::AllowReassoc>
m_AllowReassoc(const T &SubPattern) {
  return SubPattern;

Review comment (suggestion):
The `==` here should probably be `&` instead, to allow multiple flags to be used in the template parameter of the matcher.

Code after:
template <typename SubPattern_t> struct OneUse_match {
  SubPattern_t SubPattern;

  OneUse_match(const SubPattern_t &SP) : SubPattern(SP) {}

  template <typename OpTy> bool match(OpTy *V) const {
    return V->hasOneUse() && SubPattern.match(V);
  }
};

template <typename T> inline OneUse_match<T> m_OneUse(const T &SubPattern) {
  return SubPattern;
}

template <typename SubPattern_t, int Flag> struct AllowFmf_match {
  SubPattern_t SubPattern;
  FastMathFlags FMF;

  AllowFmf_match(const SubPattern_t &SP) : SubPattern(SP), FMF(Flag) {}

  template <typename OpTy> bool match(OpTy *V) const {
    auto *I = dyn_cast<FPMathOperator>(V);
    return I && ((I->getFastMathFlags() & FMF) == FMF) && SubPattern.match(I);
  }
};

template <typename T>
inline AllowFmf_match<T, FastMathFlags::AllowReassoc>
m_AllowReassoc(const T &SubPattern) {
  return SubPattern;
}

template <typename T>
inline AllowFmf_match<T, FastMathFlags::AllowReciprocal>
m_AllowReciprocal(const T &SubPattern) {
  return SubPattern;
}

template <typename T>
inline AllowFmf_match<T, FastMathFlags::AllowContract>
m_AllowContract(const T &SubPattern) {
  return SubPattern;
}

template <typename T>
inline AllowFmf_match<T, FastMathFlags::ApproxFunc>
m_ApproxFunc(const T &SubPattern) {
  return SubPattern;
}

template <typename T>
Repository: llvm/llvm-project
File: libc/src/stdio/baremetal/getc.cpp (C++)

Code before:
//===-- Implementation of getc for baremetal -------------------*- 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/getc.h"
#include "src/stdio/fgetc.h"

#include "src/__support/common.h"

namespace LIBC_NAMESPACE_DECL {

LLVM_LIBC_FUNCTION(int, getc, (::FILE * stream)) { return fgetc(stream); }

} // namespace LIBC_NAMESPACE_DECL


Review comment (refactor):
In LLVM libc we don't implement entrypoints by calling other entrypoints. If someone created their own LLVM libc configuration that only included `getc` but not `fgetc`, this code would break. Instead, this implementation should duplicate https://github.com/llvm/llvm-project/blob/5f9092a19b9f56f5ad084993df1f0cdb703c7cd8/libc/src/stdio/baremetal/fgetc.cpp#L20-L29

That may seem wasteful, but linker ICF should fold these away (another option would be to introduce an internal implementation to call from both `fgetc` and `getc` like we did e.g. with `vfscanf_internal` but for simple functions like these it's probably not worth it).

Code after:
//===-- Implementation of getc for baremetal -------------------*- 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/getc.h"

#include "hdr/stdio_macros.h" // for EOF.
#include "hdr/types/FILE.h"
#include "src/__support/common.h"
#include "src/__support/libc_errno.h"
#include "src/__support/macros/config.h"
#include "src/stdio/baremetal/file_internal.h"

namespace LIBC_NAMESPACE_DECL {

LLVM_LIBC_FUNCTION(int, getc, (::FILE * stream)) {
  unsigned char c;
  auto result = read_internal(reinterpret_cast<char *>(&c), 1, stream);
  if (result.has_error())
    libc_errno = result.error;

  if (result.value != 1)
    return EOF;
  return c;
}

} // namespace LIBC_NAMESPACE_DECL
Repository: llvm/llvm-project
File: libc/src/stdio/baremetal/fflush.cpp (C++)

Code before:
//===-- Implementation of fflush for baremetal -----------------*- 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/fflush.h"

#include "src/__support/common.h"

namespace LIBC_NAMESPACE_DECL {

// Baremetal uses unbuffered I/O, so there is nothing to flush.
LLVM_LIBC_FUNCTION(int, fflush, (::FILE * /* stream */)) { return 0; }

} // namespace LIBC_NAMESPACE_DECL


Review comment (suggestion):
We may need to introduce embedding API for this in the future, can you leave a `TODO` comment here like we did in https://github.com/llvm/llvm-project/blob/5f9092a19b9f56f5ad084993df1f0cdb703c7cd8/libc/src/stdio/baremetal/feof.cpp#L19 and https://github.com/llvm/llvm-project/blob/5f9092a19b9f56f5ad084993df1f0cdb703c7cd8/libc/src/stdio/baremetal/ferror.cpp#L19

Code after:
//===-- Implementation of fflush for baremetal -----------------*- 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/fflush.h"

#include "src/__support/common.h"

namespace LIBC_NAMESPACE_DECL {

// Baremetal uses unbuffered I/O, so there is nothing to flush.
LLVM_LIBC_FUNCTION(int, fflush, (::FILE * stream)) {
  (void)stream;
  // TODO: Shall we have an embedding API for fflush?
  return 0;
}

} // namespace LIBC_NAMESPACE_DECL
Repository: llvm/llvm-project
File: libc/src/stdio/baremetal/file_internal.cpp (C++)

Code before:
//===--- Helpers for file I/O on baremetal ----------------------*- 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/baremetal/file_internal.h"

#include "hdr/stdio_macros.h" // for EOF

namespace LIBC_NAMESPACE_DECL {

// Baremetal only exposes three fixed streams now and only stdin supports ungetc
// because stdin is readable - ungetc on stdout/stderr is undefined.
// Only one value is required by the C standard to be stored by ungetc.
extern "C" ::FILE *stdin;

struct UngetcState {
  bool has_value;
  unsigned char value;
};

static UngetcState ungetc_state_stdin{false, 0};

bool pop_ungetc_value(::FILE *stream, unsigned char &out) {
  if (stream != stdin)
    return false;

  if (ungetc_state_stdin.has_value) {
    out = ungetc_state_stdin.value;
    ungetc_state_stdin.has_value = false;
    return true;
  }
  return false;
}

int store_ungetc_value(::FILE *stream, int c) {
  if (c == EOF || stream == nullptr)
    return EOF;

  if (stream != stdin)
    return EOF;


Review comment (suggestion):
We can avoid introducing a new type using `CPP::optional<unsigned char>`

Code after:
//===--- Helpers for file I/O on baremetal ----------------------*- 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/baremetal/file_internal.h"
#include "src/__support/CPP/optional.h"

#include "hdr/stdio_macros.h" // for EOF, FILE

namespace LIBC_NAMESPACE_DECL {

// Out of standard streams only stdin supports ungetc,
// because stdin is readable - ungetc on stdout/stderr is undefined.
// Only one value is required by the C standard to be stored by ungetc.
// This minimal implementation only handles stdin and returns error on all
// other streams.
// TODO: Shall we have an embedding API for ungetc?

static cpp::optional<unsigned char> ungetc_state_stdin;

bool pop_ungetc_value(::FILE *stream, unsigned char &out) {
  if (stream != stdin)
    return false;

  if (!ungetc_state_stdin)
    return false;

  out = *ungetc_state_stdin;
  ungetc_state_stdin.reset();
  return true;
}

int push_ungetc_value(::FILE *stream, int c) {
  if (c == EOF || stream == nullptr)
    return EOF;

  if (stream != stdin)
    return EOF;

  if (ungetc_state_stdin)
    return EOF;
Repository: llvm/llvm-project
File: libc/src/stdio/baremetal/file_internal.h (C/C++)

Code before:
#include "src/__support/macros/config.h"

#include <stddef.h>

namespace LIBC_NAMESPACE_DECL {

// TODO: Deduplicate this with __support/File/file.h.
struct FileIOResult {
  size_t value;
  int error;

  constexpr FileIOResult(size_t val) : value(val), error(0) {}
  constexpr FileIOResult(size_t val, int error) : value(val), error(error) {}

  constexpr bool has_error() { return error != 0; }

  constexpr operator size_t() { return value; }
};

// ungetc handling.
int store_ungetc_value(::FILE *stream, int c);
bool pop_ungetc_value(::FILE *stream, unsigned char &out);

LIBC_INLINE FileIOResult read_internal(char *buf, size_t size, ::FILE *stream) {
  size_t ungetc_value_copied = 0;
  if (size > 0) {
    unsigned char ungetc_value = 0;
    if (pop_ungetc_value(stream, ungetc_value)) {
      buf[0] = static_cast<char>(ungetc_value);
      ungetc_value_copied = 1;
    }
  }

  if (ungetc_value_copied == size)
    return ungetc_value_copied;

  ssize_t ret = __llvm_libc_stdio_read(stream, buf + ungetc_value_copied,
                                       size - ungetc_value_copied);
  if (ret < 0)
    return {ungetc_value_copied, static_cast<int>(-ret)};
  return ret + ungetc_value_copied;
}

LIBC_INLINE FileIOResult write_internal(const char *buf, size_t size,
                                        ::FILE *stream) {
  ssize_t ret = __llvm_libc_stdio_write(stream, buf, size);
  if (ret < 0)
    return {0, static_cast<int>(-ret)};
  return ret;
}


Review comment (refactor):
Breaking this out into a guard condition on size == 0 should help clean up the logic and decrease indentation.

Code after:
#include "src/__support/macros/config.h"

#include <stddef.h>

namespace LIBC_NAMESPACE_DECL {

// TODO: Deduplicate this with __support/File/file.h.
struct FileIOResult {
  size_t value;
  int error;

  constexpr FileIOResult(size_t val) : value(val), error(0) {}
  constexpr FileIOResult(size_t val, int error) : value(val), error(error) {}

  constexpr bool has_error() { return error != 0; }

  constexpr operator size_t() { return value; }
};

// ungetc handling.
int push_ungetc_value(::FILE *stream, int c);
bool pop_ungetc_value(::FILE *stream, unsigned char &out);

LIBC_INLINE int ungetc_internal(int c, ::FILE *stream) {
  return push_ungetc_value(stream, c);
}

LIBC_INLINE FileIOResult read_internal(char *buf, size_t size, ::FILE *stream) {
  if (size == 0)
    return 0;

  unsigned char ungetc_value = 0;
  size_t ungetc_value_copied = 0;

  if (pop_ungetc_value(stream, ungetc_value)) {
    buf[0] = static_cast<char>(ungetc_value);
    ungetc_value_copied = 1;

    if (size == 1)
      return 1;
  }

  ssize_t ret = __llvm_libc_stdio_read(stream, buf + ungetc_value_copied,
                                       size - ungetc_value_copied);
  if (ret < 0)
    return {ungetc_value_copied, static_cast<int>(-ret)};

  return ret + ungetc_value_copied;
}

LIBC_INLINE FileIOResult write_internal(const char *buf, size_t size,
Repository: llvm/llvm-project
File: libc/src/stdio/baremetal/vfscanf_internal.h (C/C++)

Code before:
#include "src/__support/common.h"
#include "src/__support/libc_errno.h"
#include "src/__support/macros/config.h"
#include "src/stdio/baremetal/file_internal.h"
#include "src/stdio/scanf_core/reader.h"
#include "src/stdio/scanf_core/scanf_main.h"
#include "src/stdio/ungetc.h"

namespace LIBC_NAMESPACE_DECL {

namespace internal {

class StreamReader : public scanf_core::Reader<StreamReader> {
  ::FILE *stream;

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

  LIBC_INLINE char getc() {
    char c;
    auto result = read_internal(&c, 1, stream);
    if (result != 1)
      return '\0';
    return c;
  }
  LIBC_INLINE void ungetc(int c) { (void)LIBC_NAMESPACE::ungetc(c, stream); }
};

} // namespace internal

LIBC_INLINE int vfscanf_internal(::FILE *__restrict stream,
                                 const char *__restrict format,
                                 internal::ArgList &args) {
  internal::StreamReader reader(stream);
  // 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".
  int retval = scanf_core::scanf_main(&reader, format, args);
  return (retval == 0) ? EOF : retval;
}

} // namespace LIBC_NAMESPACE_DECL

#endif // LLVM_LIBC_SRC_STDIO_BAREMETAL_VFPRINTF_INTERNAL_H


Review comment (suggestion):
We should have an internal `ungetc` implementation and use it here rather than calling an entrypoint (in case the `ungetc` entrypoint is not included).

Code after:
#include "src/__support/common.h"
#include "src/__support/libc_errno.h"
#include "src/__support/macros/config.h"
#include "src/stdio/baremetal/file_internal.h"
#include "src/stdio/scanf_core/reader.h"
#include "src/stdio/scanf_core/scanf_main.h"

namespace LIBC_NAMESPACE_DECL {

namespace internal {

class StreamReader : public scanf_core::Reader<StreamReader> {
  ::FILE *stream;

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

  LIBC_INLINE char getc() {
    char c;
    auto result = read_internal(&c, 1, stream);
    if (result != 1)
      return '\0';
    return c;
  }
  LIBC_INLINE void ungetc(int c) { (void)ungetc_internal(c, stream); }
};

} // namespace internal

LIBC_INLINE int vfscanf_internal(::FILE *__restrict stream,
                                 const char *__restrict format,
                                 internal::ArgList &args) {
  internal::StreamReader reader(stream);
  // 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".
  int retval = scanf_core::scanf_main(&reader, format, args);
  return (retval == 0) ? EOF : retval;
}

} // namespace LIBC_NAMESPACE_DECL

#endif // LLVM_LIBC_SRC_STDIO_BAREMETAL_VFPRINTF_INTERNAL_H