Skip to content
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
25c7d79
Change writer to store chars written as size_t
mleleszi Oct 7, 2025
362c00e
Prinf internals: use -errno as return values rather than custrom erro…
mleleszi Oct 7, 2025
f8c7569
Refactor printf family functions to use PrintfResult
mleleszi Oct 7, 2025
f8f3553
Formatting
mleleszi Oct 7, 2025
4761e9a
Fix tests
mleleszi Oct 7, 2025
1dd65af
Add IO error test cases for file variants
mleleszi Oct 7, 2025
ef55545
Add overflow test for fprintf
mleleszi Oct 7, 2025
63c710b
Cleanup
mleleszi Oct 7, 2025
e035a15
Add overflow test for vfprintf
mleleszi Oct 8, 2025
56d6968
Baremetal stuff
mleleszi Oct 8, 2025
995bb08
Add test for nullptr write error
mleleszi Oct 8, 2025
eedbad9
Add overflow handling to strfrom functions
mleleszi Oct 8, 2025
242b75c
Cleanup
mleleszi Oct 10, 2025
a403604
Merge branch 'main' into libc-printf-error-handling
mleleszi Oct 10, 2025
492b9f1
Run clang-format
mleleszi Oct 10, 2025
71554f9
Fix unused param error
mleleszi Oct 10, 2025
b03c545
Refactor File to store error_code instead of error flag
mleleszi Oct 12, 2025
6d05774
Map internall err code to errno
mleleszi Oct 12, 2025
d194975
Return system IO errors return values
mleleszi Oct 17, 2025
69e9362
Use ErroOr for print retval instead of custom struct
mleleszi Oct 17, 2025
f8cb702
Fix tests
mleleszi Oct 17, 2025
0e8b25c
Fix baremetal impl
mleleszi Oct 17, 2025
756cb37
Clean up tests, dependencies
mleleszi Oct 18, 2025
463e929
Add platfrom specific error converter implementations
mleleszi Oct 23, 2025
5f3b0af
Clean up dependencies
mleleszi Oct 23, 2025
428c7e9
Add darwin and generic impl of error converter
mleleszi Oct 23, 2025
21df095
Cleanup
mleleszi Oct 31, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
#define EPIPE 32
#define EDOM 33
#define ERANGE 34
#define EOVERFLOW 75
#define EILSEQ 84

#endif // LLVM_LIBC_MACROS_GENERIC_ERROR_NUMBER_MACROS_H
16 changes: 16 additions & 0 deletions libc/src/stdio/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,9 @@ add_entrypoint_object(
DEPENDS
libc.src.stdio.printf_core.printf_main
libc.src.stdio.printf_core.writer
libc.src.stdio.printf_core.core_structs
libc.src.__support.libc_errno
libc.hdr.errno_macros
)

add_entrypoint_object(
Expand All @@ -136,6 +139,9 @@ add_entrypoint_object(
DEPENDS
libc.src.stdio.printf_core.printf_main
libc.src.stdio.printf_core.writer
libc.src.stdio.printf_core.core_structs
libc.src.__support.libc_errno
libc.hdr.errno_macros
)

add_entrypoint_object(
Expand All @@ -146,6 +152,9 @@ add_entrypoint_object(
asprintf.h
DEPENDS
libc.src.stdio.printf_core.vasprintf_internal
libc.src.stdio.printf_core.core_structs
libc.src.__support.libc_errno
libc.hdr.errno_macros
)

add_entrypoint_object(
Expand All @@ -157,6 +166,7 @@ add_entrypoint_object(
DEPENDS
libc.src.stdio.printf_core.printf_main
libc.src.stdio.printf_core.writer
libc.src.stdio.printf_core.core_structs
)

add_entrypoint_object(
Expand All @@ -168,6 +178,9 @@ add_entrypoint_object(
DEPENDS
libc.src.stdio.printf_core.printf_main
libc.src.stdio.printf_core.writer
libc.src.stdio.printf_core.core_structs
libc.src.__support.libc_errno
libc.hdr.errno_macros
)

add_entrypoint_object(
Expand All @@ -178,6 +191,9 @@ add_entrypoint_object(
vasprintf.h
DEPENDS
libc.src.stdio.printf_core.vasprintf_internal
libc.src.stdio.printf_core.core_structs
libc.src.__support.libc_errno
libc.hdr.errno_macros
)

add_subdirectory(printf_core)
Expand Down
15 changes: 13 additions & 2 deletions libc/src/stdio/asprintf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
//===----------------------------------------------------------------------===//

#include "src/stdio/asprintf.h"
#include "hdr/errno_macros.h"
#include "src/__support/arg_list.h"
#include "src/__support/libc_errno.h"
#include "src/__support/macros/config.h"
#include "src/stdio/printf_core/vasprintf_internal.h"

Expand All @@ -22,8 +24,17 @@ LLVM_LIBC_FUNCTION(int, asprintf,
// and pointer semantics, as well as handling
// destruction automatically.
va_end(vlist);
int ret = printf_core::vasprintf_internal(buffer, format, args);
return ret;
auto ret_val = printf_core::vasprintf_internal(buffer, format, args);
if (!ret_val.has_value()) {
libc_errno = printf_core::internal_error_to_errno(ret_val.error());
return -1;
}
if (ret_val.value() > cpp::numeric_limits<int>::max()) {
libc_errno = EOVERFLOW;
return -1;
}

return static_cast<int>(ret_val.value());
}

} // namespace LIBC_NAMESPACE_DECL
2 changes: 2 additions & 0 deletions libc/src/stdio/baremetal/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ add_entrypoint_object(
libc.src.stdio.printf_core.writer
libc.src.__support.arg_list
libc.src.__support.OSUtil.osutil
libc.src.__support.libc_errno
)

add_entrypoint_object(
Expand Down Expand Up @@ -89,6 +90,7 @@ add_entrypoint_object(
libc.src.stdio.printf_core.writer
libc.src.__support.arg_list
libc.src.__support.OSUtil.osutil
libc.src.__support.libc_errno
)

add_entrypoint_object(
Expand Down
20 changes: 16 additions & 4 deletions libc/src/stdio/baremetal/printf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "src/stdio/printf.h"
#include "src/__support/OSUtil/io.h"
#include "src/__support/arg_list.h"
#include "src/__support/libc_errno.h"
#include "src/__support/macros/config.h"
#include "src/stdio/printf_core/core_structs.h"
#include "src/stdio/printf_core/printf_main.h"
Expand Down Expand Up @@ -42,13 +43,24 @@ LLVM_LIBC_FUNCTION(int, printf, (const char *__restrict format, ...)) {
buffer, BUFF_SIZE, &stdout_write_hook, nullptr);
printf_core::Writer<printf_core::WriteMode::FLUSH_TO_STREAM> writer(wb);

int retval = printf_core::printf_main(&writer, format, args);
auto retval = printf_core::printf_main(&writer, format, args);
if (!retval.has_value()) {
libc_errno = printf_core::internal_error_to_errno(retval.error());
return -1;
}

int flushval = wb.overflow_write("");
if (flushval != printf_core::WRITE_OK)
retval = flushval;
if (flushval != printf_core::WRITE_OK) {
libc_errno = printf_core::internal_error_to_errno(-flushval);
return -1;
}

return retval;
if (retval.value() > cpp::numeric_limits<int>::max()) {
libc_errno = EOVERFLOW;
return -1;
}

return static_cast<int>(retval.value());
}

} // namespace LIBC_NAMESPACE_DECL
21 changes: 17 additions & 4 deletions libc/src/stdio/baremetal/vprintf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
//===----------------------------------------------------------------------===//

#include "src/stdio/vprintf.h"
#include "hdr/errno_macros.h"
#include "src/__support/OSUtil/io.h"
#include "src/__support/arg_list.h"
#include "src/__support/libc_errno.h"
#include "src/__support/macros/config.h"
#include "src/stdio/printf_core/core_structs.h"
#include "src/stdio/printf_core/printf_main.h"
Expand Down Expand Up @@ -40,13 +42,24 @@ LLVM_LIBC_FUNCTION(int, vprintf,
buffer, BUFF_SIZE, &stdout_write_hook, nullptr);
printf_core::Writer<printf_core::WriteMode::FLUSH_TO_STREAM> writer(wb);

int retval = printf_core::printf_main(&writer, format, args);
auto retval = printf_core::printf_main(&writer, format, args);
if (!retval.has_value()) {
libc_errno = printf_core::internal_error_to_errno(retval.error());
return -1;
}

int flushval = wb.overflow_write("");
if (flushval != printf_core::WRITE_OK)
retval = flushval;
if (flushval != printf_core::WRITE_OK) {
libc_errno = printf_core::internal_error_to_errno(-flushval);
return -1;
}

return retval;
if (retval.value() > cpp::numeric_limits<int>::max()) {
libc_errno = EOVERFLOW;
return -1;
}

return static_cast<int>(retval.value());
}

} // namespace LIBC_NAMESPACE_DECL
1 change: 1 addition & 0 deletions libc/src/stdio/generic/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,7 @@ list(APPEND fprintf_deps
libc.hdr.types.FILE
libc.src.__support.arg_list
libc.src.stdio.printf_core.vfprintf_internal
libc.src.stdio.printf_core.core_structs
)

if(LLVM_LIBC_FULL_BUILD)
Expand Down
13 changes: 11 additions & 2 deletions libc/src/stdio/generic/fprintf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,17 @@ LLVM_LIBC_FUNCTION(int, fprintf,
// and pointer semantics, as well as handling
// destruction automatically.
va_end(vlist);
int ret_val = printf_core::vfprintf_internal(stream, format, args);
return ret_val;
auto ret_val = printf_core::vfprintf_internal(stream, format, args);
if (!ret_val.has_value()) {
libc_errno = printf_core::internal_error_to_errno(ret_val.error());
return -1;
}
if (ret_val.value() > cpp::numeric_limits<int>::max()) {
libc_errno = EOVERFLOW;
return -1;
}

return static_cast<int>(ret_val.value());
}

} // namespace LIBC_NAMESPACE_DECL
14 changes: 12 additions & 2 deletions libc/src/stdio/generic/printf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "src/__support/File/file.h"
#include "src/__support/arg_list.h"
#include "src/__support/macros/config.h"
#include "src/stdio/printf_core/core_structs.h"
#include "src/stdio/printf_core/vfprintf_internal.h"

#include "hdr/types/FILE.h"
Expand All @@ -31,9 +32,18 @@ LLVM_LIBC_FUNCTION(int, printf, (const char *__restrict format, ...)) {
// and pointer semantics, as well as handling
// destruction automatically.
va_end(vlist);
int ret_val = printf_core::vfprintf_internal(
auto ret_val = printf_core::vfprintf_internal(
reinterpret_cast<::FILE *>(PRINTF_STDOUT), format, args);
return ret_val;
if (!ret_val.has_value()) {
libc_errno = printf_core::internal_error_to_errno(ret_val.error());
return -1;
}
if (ret_val.value() > cpp::numeric_limits<int>::max()) {
libc_errno = EOVERFLOW;
return -1;
}

return static_cast<int>(ret_val.value());
}

} // namespace LIBC_NAMESPACE_DECL
14 changes: 12 additions & 2 deletions libc/src/stdio/generic/vfprintf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "src/__support/File/file.h"
#include "src/__support/arg_list.h"
#include "src/__support/macros/config.h"
#include "src/stdio/printf_core/core_structs.h"
#include "src/stdio/printf_core/vfprintf_internal.h"

#include "hdr/types/FILE.h"
Expand All @@ -24,8 +25,17 @@ LLVM_LIBC_FUNCTION(int, vfprintf,
internal::ArgList args(vlist); // This holder class allows for easier copying
// and pointer semantics, as well as handling
// destruction automatically.
int ret_val = printf_core::vfprintf_internal(stream, format, args);
return ret_val;
auto ret_val = printf_core::vfprintf_internal(stream, format, args);
if (!ret_val.has_value()) {
libc_errno = printf_core::internal_error_to_errno(ret_val.error());
return -1;
}
if (ret_val.value() > cpp::numeric_limits<int>::max()) {
libc_errno = EOVERFLOW;
return -1;
}

return static_cast<int>(ret_val.value());
}

} // namespace LIBC_NAMESPACE_DECL
13 changes: 11 additions & 2 deletions libc/src/stdio/generic/vprintf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,18 @@ LLVM_LIBC_FUNCTION(int, vprintf,
internal::ArgList args(vlist); // This holder class allows for easier copying
// and pointer semantics, as well as handling
// destruction automatically.
int ret_val = printf_core::vfprintf_internal(
auto ret_val = printf_core::vfprintf_internal(
reinterpret_cast<::FILE *>(PRINTF_STDOUT), format, args);
return ret_val;
if (!ret_val.has_value()) {
libc_errno = printf_core::internal_error_to_errno(ret_val.error());
return -1;
}
if (ret_val.value() > cpp::numeric_limits<int>::max()) {
libc_errno = EOVERFLOW;
return -1;
}

return static_cast<int>(ret_val.value());
}

} // namespace LIBC_NAMESPACE_DECL
4 changes: 4 additions & 0 deletions libc/src/stdio/printf_core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ add_header_library(
libc.include.inttypes
libc.src.__support.CPP.string_view
libc.src.__support.FPUtil.fp_bits
libc.hdr.errno_macros
)

add_header_library(
Expand Down Expand Up @@ -125,6 +126,7 @@ add_header_library(
.writer
.core_structs
libc.src.__support.arg_list
libc.src.__support.error_or
)

add_header_library(
Expand All @@ -136,6 +138,7 @@ add_header_library(
libc.hdr.func.free
libc.hdr.func.realloc
libc.src.__support.arg_list
libc.src.__support.error_or
libc.src.stdio.printf_core.printf_main
libc.src.stdio.printf_core.writer
)
Expand All @@ -152,6 +155,7 @@ add_header_library(
vfprintf_internal.h
DEPENDS
libc.src.__support.File.file
libc.src.__support.error_or
libc.src.__support.arg_list
libc.src.stdio.printf_core.printf_main
libc.src.stdio.printf_core.writer
Expand Down
49 changes: 41 additions & 8 deletions libc/src/stdio/printf_core/core_structs.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

#include "src/__support/macros/config.h"

#include "hdr/errno_macros.h"
#include "src/__support/CPP/string_view.h"
#include "src/__support/CPP/type_traits.h"
#include "src/__support/FPUtil/FPBits.h"
Expand Down Expand Up @@ -132,14 +133,46 @@ template <typename T> LIBC_INLINE constexpr TypeDesc type_desc_from_type() {

// This is the value to be returned by conversions when no error has occurred.
constexpr int WRITE_OK = 0;
// These are the printf return values for when an error has occurred. They are
// all negative, and should be distinct.
constexpr int FILE_WRITE_ERROR = -1;
constexpr int FILE_STATUS_ERROR = -2;
constexpr int NULLPTR_WRITE_ERROR = -3;
constexpr int INT_CONVERSION_ERROR = -4;
constexpr int FIXED_POINT_CONVERSION_ERROR = -5;
constexpr int ALLOCATION_ERROR = -6;
// These are the error return values used by the printf engine when an
// error has occurred. They are all large negative, distinct values starting
// from -1000 to not overlap with system errors.
constexpr int FILE_WRITE_ERROR = -1001;
constexpr int FILE_STATUS_ERROR = -1002;
constexpr int NULLPTR_WRITE_ERROR = -1003;
constexpr int INT_CONVERSION_ERROR = -1004;
constexpr int FIXED_POINT_CONVERSION_ERROR = -1005;
constexpr int ALLOCATION_ERROR = -1006;

LIBC_INLINE static int internal_error_to_errno(int internal_error) {
// System error occured, return error as is.
if (internal_error < 1001) {
return internal_error;
}

// Map internal error to errno.
switch (-internal_error) {
case WRITE_OK:
return 0;
case FILE_WRITE_ERROR:
return EIO;
case FILE_STATUS_ERROR:
return EIO;
case NULLPTR_WRITE_ERROR:
return EINVAL;
case INT_CONVERSION_ERROR:
return ERANGE;
case FIXED_POINT_CONVERSION_ERROR:
return EINVAL;
case ALLOCATION_ERROR:
return ENOMEM;
default:
LIBC_ASSERT(
false &&
"Invalid internal printf error code passed to internal_error_to_errno");
return EINVAL;
}
}

} // namespace printf_core
} // namespace LIBC_NAMESPACE_DECL

Expand Down
1 change: 1 addition & 0 deletions libc/src/stdio/printf_core/int_converter.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#ifndef LLVM_LIBC_SRC_STDIO_PRINTF_CORE_INT_CONVERTER_H
#define LLVM_LIBC_SRC_STDIO_PRINTF_CORE_INT_CONVERTER_H

#include "hdr/errno_macros.h"
#include "src/__support/CPP/span.h"
#include "src/__support/CPP/string_view.h"
#include "src/__support/ctype_utils.h"
Expand Down
Loading
Loading