[libc-commits] [libc] cff4ca2 - [libc] Implement tmpfile and corresponding tests (#213396)

via libc-commits libc-commits at lists.llvm.org
Tue Aug 11 12:58:54 PDT 2026


Author: Vadim Kotov
Date: 2026-08-11T12:58:49-07:00
New Revision: cff4ca2e51f89c992d8a1b6ce1067846ba680e2e

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

LOG: [libc] Implement tmpfile and corresponding tests (#213396)

Closes issue #191281.

Added: 
    libc/src/stdio/linux/tmpfile.cpp
    libc/src/stdio/tmpfile.h
    libc/test/src/stdio/tmpfile_test.cpp

Modified: 
    libc/config/linux/aarch64/entrypoints.txt
    libc/config/linux/arm/entrypoints.txt
    libc/config/linux/riscv/entrypoints.txt
    libc/config/linux/x86_64/entrypoints.txt
    libc/include/stdio.yaml
    libc/src/stdio/CMakeLists.txt
    libc/src/stdio/linux/CMakeLists.txt
    libc/test/src/stdio/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 9e9f3704acc11..8d48ab7c23d61 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -254,6 +254,7 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.stdio.stderr
     libc.src.stdio.stdin
     libc.src.stdio.stdout
+    libc.src.stdio.tmpfile
     libc.src.stdio.vsscanf
     libc.src.stdio.vfprintf
     libc.src.stdio.vprintf

diff  --git a/libc/config/linux/arm/entrypoints.txt b/libc/config/linux/arm/entrypoints.txt
index 9a56ab5ee80b6..2d517cb6cf20a 100644
--- a/libc/config/linux/arm/entrypoints.txt
+++ b/libc/config/linux/arm/entrypoints.txt
@@ -192,6 +192,9 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.stdlib.free
     libc.src.stdlib.malloc
 
+    # stdio.h entrypoints
+    libc.src.stdio.tmpfile
+
     # sys/ioctl.h entrypoints
     libc.src.sys.ioctl.ioctl
 

diff  --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index 0c33742de70a7..2da2cf52a6c68 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -277,6 +277,7 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.stdio.stderr
     libc.src.stdio.stdin
     libc.src.stdio.stdout
+    libc.src.stdio.tmpfile
     libc.src.stdio.vsscanf
     libc.src.stdio.vfprintf
     libc.src.stdio.vprintf

diff  --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index e54cd22f0f43e..79f87510c51ed 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -277,6 +277,7 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.stdio.stderr
     libc.src.stdio.stdin
     libc.src.stdio.stdout
+    libc.src.stdio.tmpfile
     libc.src.stdio.vsscanf
     libc.src.stdio.vfprintf
     libc.src.stdio.vprintf

diff  --git a/libc/include/stdio.yaml b/libc/include/stdio.yaml
index 4b12698e2484d..a5feb29272971 100644
--- a/libc/include/stdio.yaml
+++ b/libc/include/stdio.yaml
@@ -396,6 +396,12 @@ functions:
       - type: const char *__restrict
       - type: const char *__restrict
       - type: '...'
+  - name: tmpfile
+    standards:
+      - stdc
+    return_type: FILE *
+    arguments:
+      - type: void
   - name: ungetc
     standards:
       - stdc

diff  --git a/libc/src/stdio/CMakeLists.txt b/libc/src/stdio/CMakeLists.txt
index cfbe67e825aa3..68ee57fae646d 100644
--- a/libc/src/stdio/CMakeLists.txt
+++ b/libc/src/stdio/CMakeLists.txt
@@ -256,6 +256,13 @@ add_entrypoint_object(
     .${LIBC_TARGET_OS}.fdopen
 )
 
+add_entrypoint_object(
+  tmpfile
+  ALIAS
+  DEPENDS
+    .${LIBC_TARGET_OS}.tmpfile
+)
+
 # These entrypoints have multiple potential implementations.
 add_stdio_entrypoint_object(feof)
 add_stdio_entrypoint_object(feof_unlocked)

diff  --git a/libc/src/stdio/linux/CMakeLists.txt b/libc/src/stdio/linux/CMakeLists.txt
index 218875c78e246..6631f2ca4814a 100644
--- a/libc/src/stdio/linux/CMakeLists.txt
+++ b/libc/src/stdio/linux/CMakeLists.txt
@@ -66,3 +66,19 @@ add_entrypoint_object(
     libc.hdr.types.FILE
     libc.src.__support.File.platform_file
 )
+
+add_entrypoint_object(
+  tmpfile
+  SRCS
+    tmpfile.cpp
+  HDRS
+    ../tmpfile.h
+  DEPENDS
+    libc.hdr.fcntl_macros
+    libc.hdr.types.FILE
+    libc.src.__support.common
+    libc.src.__support.File.platform_file
+    libc.src.__support.libc_errno
+    libc.src.__support.macros.config
+    libc.src.__support.OSUtil.linux.syscall_wrappers.open
+)

diff  --git a/libc/src/stdio/linux/tmpfile.cpp b/libc/src/stdio/linux/tmpfile.cpp
new file mode 100644
index 0000000000000..3758a6fadc627
--- /dev/null
+++ b/libc/src/stdio/linux/tmpfile.cpp
@@ -0,0 +1,41 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Linux implementation of tmpfile.
+///
+//===----------------------------------------------------------------------===//
+#include "src/stdio/tmpfile.h"
+#include "hdr/fcntl_macros.h"
+#include "hdr/types/FILE.h"
+#include "src/__support/OSUtil/linux/syscall_wrappers/open.h"
+
+#include "src/__support/File/linux/file.h"
+#include "src/__support/common.h"
+#include "src/__support/libc_errno.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+constexpr char TMPDIR[] = "/tmp";
+
+LLVM_LIBC_FUNCTION(::FILE *, tmpfile, (void)) {
+  auto fd = linux_syscalls::open(TMPDIR, O_RDWR | O_TMPFILE | O_EXCL, 0600);
+  if (!fd.has_value()) {
+    libc_errno = fd.error();
+    return nullptr;
+  }
+  auto file = LIBC_NAMESPACE::create_file_from_fd(fd.value(), "w+b");
+  if (!file.has_value()) {
+    libc_errno = file.error();
+    return nullptr;
+  }
+  return reinterpret_cast<::FILE *>(file.value());
+}
+
+} // namespace LIBC_NAMESPACE_DECL

diff  --git a/libc/src/stdio/tmpfile.h b/libc/src/stdio/tmpfile.h
new file mode 100644
index 0000000000000..8d8185f4b4d34
--- /dev/null
+++ b/libc/src/stdio/tmpfile.h
@@ -0,0 +1,26 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Implementation header of tmpfile.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_STDIO_TMPFILE_H_
+#define LLVM_LIBC_SRC_STDIO_TMPFILE_H_
+
+#include "hdr/types/FILE.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+::FILE *tmpfile();
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STDIO_TMPFILE_H_

diff  --git a/libc/test/src/stdio/CMakeLists.txt b/libc/test/src/stdio/CMakeLists.txt
index 600a0a6fd567d..6ec484129dee2 100644
--- a/libc/test/src/stdio/CMakeLists.txt
+++ b/libc/test/src/stdio/CMakeLists.txt
@@ -593,6 +593,21 @@ add_libc_test(
     libc.src.stdio.setvbuf
 )
 
+add_libc_test(
+  tmpfile_test
+  SUITE
+    libc_stdio_unittests
+  SRCS
+    tmpfile_test.cpp
+  DEPENDS
+    libc.src.stdio.tmpfile
+    libc.src.stdio.fflush
+    libc.src.stdio.fread
+    libc.src.stdio.fseek
+    libc.src.stdio.ftell
+    libc.src.stdio.fwrite
+)
+
 # Create an output directory for any temporary test files.
 file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/testdata)
 

diff  --git a/libc/test/src/stdio/tmpfile_test.cpp b/libc/test/src/stdio/tmpfile_test.cpp
new file mode 100644
index 0000000000000..66a7b73361789
--- /dev/null
+++ b/libc/test/src/stdio/tmpfile_test.cpp
@@ -0,0 +1,46 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Unittests for tmpfile.
+///
+//===----------------------------------------------------------------------===//
+
+#include "hdr/stdio_macros.h"
+#include "src/stdio/fclose.h"
+#include "src/stdio/fflush.h"
+#include "src/stdio/fread.h"
+#include "src/stdio/fseek.h"
+#include "src/stdio/ftell.h"
+#include "src/stdio/fwrite.h"
+#include "src/stdio/tmpfile.h"
+#include "test/UnitTest/Test.h"
+
+constexpr char TEST_STR[] = "test\xaa\t\xbb";
+constexpr size_t TEST_STR_SIZE = sizeof(TEST_STR);
+
+TEST(LlvmLibcTmpfileTest, CreationAndInvariants) {
+  auto *file = LIBC_NAMESPACE::tmpfile();
+  ASSERT_NE(file, nullptr);
+
+  EXPECT_EQ(LIBC_NAMESPACE::ftell(file), 0L);
+
+  size_t nbytes_written =
+      LIBC_NAMESPACE::fwrite(TEST_STR, 1, TEST_STR_SIZE, file);
+  EXPECT_EQ(nbytes_written, TEST_STR_SIZE);
+
+  EXPECT_EQ(LIBC_NAMESPACE::fflush(file), 0);
+  EXPECT_EQ(static_cast<size_t>(LIBC_NAMESPACE::ftell(file)), nbytes_written);
+
+  EXPECT_EQ(LIBC_NAMESPACE::fseek(file, 0, SEEK_SET), 0);
+  EXPECT_EQ(LIBC_NAMESPACE::ftell(file), 0L);
+
+  char buff[TEST_STR_SIZE * 2];
+  size_t nbytes_read = LIBC_NAMESPACE::fread(buff, 1, TEST_STR_SIZE, file);
+  EXPECT_EQ(nbytes_read, TEST_STR_SIZE);
+}


        


More information about the libc-commits mailing list