[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