[libc-commits] [libc] [llvm] [libc][math] Implement nan(f|l) functions (PR #76690)
Nishant Mittal via libc-commits
libc-commits at lists.llvm.org
Wed Jan 3 23:55:59 PST 2024
https://github.com/nishantwrp updated https://github.com/llvm/llvm-project/pull/76690
>From f5dbcc5c5902fe9fce0861e6a8799ffe42ad1357 Mon Sep 17 00:00:00 2001
From: Nishant Mittal <nishantwrp at google.com>
Date: Mon, 1 Jan 2024 20:16:45 +0000
Subject: [PATCH 1/5] [libc][math] Implement nan(f|l) functions
---
libc/config/darwin/arm/entrypoints.txt | 3 +
libc/config/darwin/x86_64/entrypoints.txt | 3 +
libc/config/gpu/entrypoints.txt | 2 +
libc/config/linux/aarch64/entrypoints.txt | 3 +
libc/config/linux/riscv/entrypoints.txt | 3 +
libc/config/linux/x86_64/entrypoints.txt | 3 +
libc/config/windows/entrypoints.txt | 3 +
libc/docs/math/index.rst | 6 +-
libc/spec/stdc.td | 4 ++
libc/src/__support/str_to_float.h | 28 ++++++++
libc/src/math/CMakeLists.txt | 4 ++
libc/src/math/generic/CMakeLists.txt | 39 +++++++++++
libc/src/math/generic/nan.cpp | 26 ++++++++
libc/src/math/generic/nanf.cpp | 26 ++++++++
libc/src/math/generic/nanl.cpp | 26 ++++++++
libc/src/math/nan.h | 18 ++++++
libc/src/math/nanf.h | 18 ++++++
libc/src/math/nanl.h | 18 ++++++
libc/test/src/math/smoke/CMakeLists.txt | 36 +++++++++++
libc/test/src/math/smoke/nan_test.cpp | 40 ++++++++++++
libc/test/src/math/smoke/nanf_test.cpp | 40 ++++++++++++
libc/test/src/math/smoke/nanl_test.cpp | 64 +++++++++++++++++++
.../llvm-project-overlay/libc/BUILD.bazel | 6 ++
23 files changed, 416 insertions(+), 3 deletions(-)
create mode 100644 libc/src/math/generic/nan.cpp
create mode 100644 libc/src/math/generic/nanf.cpp
create mode 100644 libc/src/math/generic/nanl.cpp
create mode 100644 libc/src/math/nan.h
create mode 100644 libc/src/math/nanf.h
create mode 100644 libc/src/math/nanl.h
create mode 100644 libc/test/src/math/smoke/nan_test.cpp
create mode 100644 libc/test/src/math/smoke/nanf_test.cpp
create mode 100644 libc/test/src/math/smoke/nanl_test.cpp
diff --git a/libc/config/darwin/arm/entrypoints.txt b/libc/config/darwin/arm/entrypoints.txt
index da4a2345f389c4..02a09256606956 100644
--- a/libc/config/darwin/arm/entrypoints.txt
+++ b/libc/config/darwin/arm/entrypoints.txt
@@ -193,6 +193,9 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.modf
libc.src.math.modff
libc.src.math.modfl
+ libc.src.math.nan
+ libc.src.math.nanf
+ libc.src.math.nanl
libc.src.math.nearbyint
libc.src.math.nearbyintf
libc.src.math.nearbyintl
diff --git a/libc/config/darwin/x86_64/entrypoints.txt b/libc/config/darwin/x86_64/entrypoints.txt
index e29e75ec92dadc..91493cb77b1d86 100644
--- a/libc/config/darwin/x86_64/entrypoints.txt
+++ b/libc/config/darwin/x86_64/entrypoints.txt
@@ -172,6 +172,9 @@ set(TARGET_LIBM_ENTRYPOINTS
#libc.src.math.modf
#libc.src.math.modff
#libc.src.math.modfl
+ #libc.src.math.nan
+ #libc.src.math.nanf
+ #libc.src.math.nanl
#libc.src.math.nearbyint
#libc.src.math.nearbyintf
#libc.src.math.nearbyintl
diff --git a/libc/config/gpu/entrypoints.txt b/libc/config/gpu/entrypoints.txt
index ba86e31ee0adcd..b333c6be144627 100644
--- a/libc/config/gpu/entrypoints.txt
+++ b/libc/config/gpu/entrypoints.txt
@@ -215,6 +215,8 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.lroundf
libc.src.math.modf
libc.src.math.modff
+ libc.src.math.nan
+ libc.src.math.nanf
libc.src.math.nearbyint
libc.src.math.nearbyintf
libc.src.math.nextafter
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 77c9a50b8b7e5d..ce3f5eb40e38aa 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -313,6 +313,9 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.modf
libc.src.math.modff
libc.src.math.modfl
+ libc.src.math.nan
+ libc.src.math.nanf
+ libc.src.math.nanl
libc.src.math.nearbyint
libc.src.math.nearbyintf
libc.src.math.nearbyintl
diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index e389936ffca1ef..ec2a16f5cf473b 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -322,6 +322,9 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.modf
libc.src.math.modff
libc.src.math.modfl
+ libc.src.math.nan
+ libc.src.math.nanf
+ libc.src.math.nanl
libc.src.math.nearbyint
libc.src.math.nearbyintf
libc.src.math.nearbyintl
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 3adcd57d0c0849..30900de365bf95 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -323,6 +323,9 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.modf
libc.src.math.modff
libc.src.math.modfl
+ libc.src.math.nan
+ libc.src.math.nanf
+ libc.src.math.nanl
libc.src.math.nearbyint
libc.src.math.nearbyintf
libc.src.math.nearbyintl
diff --git a/libc/config/windows/entrypoints.txt b/libc/config/windows/entrypoints.txt
index 4c0a6ec37fe4cc..5c3a2e287b9529 100644
--- a/libc/config/windows/entrypoints.txt
+++ b/libc/config/windows/entrypoints.txt
@@ -192,6 +192,9 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.modf
libc.src.math.modff
libc.src.math.modfl
+ libc.src.math.nan
+ libc.src.math.nanf
+ libc.src.math.nanl
libc.src.math.nearbyint
libc.src.math.nearbyintf
libc.src.math.nearbyintl
diff --git a/libc/docs/math/index.rst b/libc/docs/math/index.rst
index eaa7a40a29ae73..3668524af03c27 100644
--- a/libc/docs/math/index.rst
+++ b/libc/docs/math/index.rst
@@ -212,11 +212,11 @@ Basic Operations
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
| modfl | |check| | |check| | | |check| | |check| | | | |check| | | | | |
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
-| nan | | | | | | | | | | | | |
+| nan | |check| | |check| | | |check| | |check| | | | |check| | | | | |
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
-| nanf | | | | | | | | | | | | |
+| nanf | |check| | |check| | | |check| | |check| | | | |check| | | | | |
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
-| nanl | | | | | | | | | | | | |
+| nanl | |check| | |check| | | |check| | |check| | | | |check| | | | | |
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
| nearbyint | |check| | |check| | | |check| | |check| | | | |check| | | | | |
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td
index 58c95b856535a1..78095eb23f0711 100644
--- a/libc/spec/stdc.td
+++ b/libc/spec/stdc.td
@@ -515,6 +515,10 @@ def StdC : StandardSpec<"stdc"> {
FunctionSpec<"scalbn", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<IntType>]>,
FunctionSpec<"scalbnf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<IntType>]>,
FunctionSpec<"scalbnl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<IntType>]>,
+
+ FunctionSpec<"nanf", RetValSpec<FloatType>, [ArgSpec<ConstCharPtr>]>,
+ FunctionSpec<"nan", RetValSpec<DoubleType>, [ArgSpec<ConstCharPtr>]>,
+ FunctionSpec<"nanl", RetValSpec<LongDoubleType>, [ArgSpec<ConstCharPtr>]>,
]
>;
diff --git a/libc/src/__support/str_to_float.h b/libc/src/__support/str_to_float.h
index 36b512d6972a93..555f65707b4e41 100644
--- a/libc/src/__support/str_to_float.h
+++ b/libc/src/__support/str_to_float.h
@@ -1206,6 +1206,34 @@ LIBC_INLINE StrToNumResult<T> strtofloatingpoint(const char *__restrict src) {
return {T(result), index, error};
}
+LIBC_INLINE const char *nan_str_to_floatingpoint_str(const char *arg) {
+ ptrdiff_t index = 0;
+ while (isalnum(arg[index]) || arg[index] == '_')
+ ++index;
+
+ if (arg[index] == '\0') {
+ // 5 is the number of characters in string "NAN()".
+ ptrdiff_t size = 5 + index;
+ char *output_str = new char[size + 1];
+
+ output_str[0] = 'N';
+ output_str[1] = 'A';
+ output_str[2] = 'N';
+ output_str[3] = '(';
+
+ for (ptrdiff_t i = 0; i < index; ++i) {
+ output_str[4 + i] = arg[i];
+ }
+
+ output_str[size - 1] = ')';
+ output_str[size] = '\0';
+
+ return output_str;
+ }
+
+ return "NAN";
+}
+
} // namespace internal
} // namespace LIBC_NAMESPACE
diff --git a/libc/src/math/CMakeLists.txt b/libc/src/math/CMakeLists.txt
index ffabc27bc00abc..e2b1026fcad7e5 100644
--- a/libc/src/math/CMakeLists.txt
+++ b/libc/src/math/CMakeLists.txt
@@ -179,6 +179,10 @@ add_math_entrypoint_object(modf)
add_math_entrypoint_object(modff)
add_math_entrypoint_object(modfl)
+add_math_entrypoint_object(nan)
+add_math_entrypoint_object(nanf)
+add_math_entrypoint_object(nanl)
+
add_math_entrypoint_object(nearbyint)
add_math_entrypoint_object(nearbyintf)
add_math_entrypoint_object(nearbyintl)
diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt
index 214d57842d93b5..eeb09652961fd5 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -1437,6 +1437,45 @@ add_entrypoint_object(
-O3
)
+add_entrypoint_object(
+ nan
+ SRCS
+ nan.cpp
+ HDRS
+ ../nan.h
+ DEPENDS
+ libc.src.__support.str_to_float
+ libc.src.errno.errno
+ COMPILE_OPTIONS
+ -O3
+)
+
+add_entrypoint_object(
+ nanf
+ SRCS
+ nanf.cpp
+ HDRS
+ ../nanf.h
+ DEPENDS
+ libc.src.__support.str_to_float
+ libc.src.errno.errno
+ COMPILE_OPTIONS
+ -O3
+)
+
+add_entrypoint_object(
+ nanl
+ SRCS
+ nanl.cpp
+ HDRS
+ ../nanl.h
+ DEPENDS
+ libc.src.__support.str_to_float
+ libc.src.errno.errno
+ COMPILE_OPTIONS
+ -O3
+)
+
add_entrypoint_object(
nextafter
SRCS
diff --git a/libc/src/math/generic/nan.cpp b/libc/src/math/generic/nan.cpp
new file mode 100644
index 00000000000000..9d591dcd3d091b
--- /dev/null
+++ b/libc/src/math/generic/nan.cpp
@@ -0,0 +1,26 @@
+//===-- Implementation of nan function ------------------------------------===//
+//
+// 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/math/nan.h"
+#include "src/__support/common.h"
+#include "src/__support/str_to_float.h"
+#include "src/errno/libc_errno.h"
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(double, nan, (const char *arg)) {
+ const char *fp_str = internal::nan_str_to_floatingpoint_str(arg);
+ auto result = internal::strtofloatingpoint<double>(fp_str);
+
+ if (result.has_error())
+ libc_errno = result.error;
+
+ return result.value;
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/math/generic/nanf.cpp b/libc/src/math/generic/nanf.cpp
new file mode 100644
index 00000000000000..b83e715485e471
--- /dev/null
+++ b/libc/src/math/generic/nanf.cpp
@@ -0,0 +1,26 @@
+//===-- Implementation of nanf function -----------------------------------===//
+//
+// 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/math/nanf.h"
+#include "src/__support/common.h"
+#include "src/__support/str_to_float.h"
+#include "src/errno/libc_errno.h"
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(float, nanf, (const char *arg)) {
+ const char *fp_str = internal::nan_str_to_floatingpoint_str(arg);
+ auto result = internal::strtofloatingpoint<float>(fp_str);
+
+ if (result.has_error())
+ libc_errno = result.error;
+
+ return result.value;
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/math/generic/nanl.cpp b/libc/src/math/generic/nanl.cpp
new file mode 100644
index 00000000000000..6f70af9957b426
--- /dev/null
+++ b/libc/src/math/generic/nanl.cpp
@@ -0,0 +1,26 @@
+//===-- Implementation of nanl function -----------------------------------===//
+//
+// 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/math/nanl.h"
+#include "src/__support/common.h"
+#include "src/__support/str_to_float.h"
+#include "src/errno/libc_errno.h"
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(long double, nanl, (const char *arg)) {
+ const char *fp_str = internal::nan_str_to_floatingpoint_str(arg);
+ auto result = internal::strtofloatingpoint<long double>(fp_str);
+
+ if (result.has_error())
+ libc_errno = result.error;
+
+ return result.value;
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/math/nan.h b/libc/src/math/nan.h
new file mode 100644
index 00000000000000..463940b01a2720
--- /dev/null
+++ b/libc/src/math/nan.h
@@ -0,0 +1,18 @@
+//===-- Implementation header for nan ---------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_MATH_NAN_H
+#define LLVM_LIBC_SRC_MATH_NAN_H
+
+namespace LIBC_NAMESPACE {
+
+double nan(const char *arg);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_MATH_NAN_H
diff --git a/libc/src/math/nanf.h b/libc/src/math/nanf.h
new file mode 100644
index 00000000000000..f05d60e3a96718
--- /dev/null
+++ b/libc/src/math/nanf.h
@@ -0,0 +1,18 @@
+//===-- Implementation header for nanf --------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_MATH_NANF_H
+#define LLVM_LIBC_SRC_MATH_NANF_H
+
+namespace LIBC_NAMESPACE {
+
+float nanf(const char *arg);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_MATH_NANF_H
diff --git a/libc/src/math/nanl.h b/libc/src/math/nanl.h
new file mode 100644
index 00000000000000..d8bbce7cc1bcc3
--- /dev/null
+++ b/libc/src/math/nanl.h
@@ -0,0 +1,18 @@
+//===-- Implementation header for nanl --------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_MATH_NANL_H
+#define LLVM_LIBC_SRC_MATH_NANL_H
+
+namespace LIBC_NAMESPACE {
+
+long double nanl(const char *arg);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_MATH_NANL_H
diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt
index 6ebd374d04a5ba..6488f9f86f1fd3 100644
--- a/libc/test/src/math/smoke/CMakeLists.txt
+++ b/libc/test/src/math/smoke/CMakeLists.txt
@@ -1203,6 +1203,42 @@ add_fp_unittest(
libc.src.__support.FPUtil.fp_bits
)
+add_fp_unittest(
+ nanf_test
+ SUITE
+ libc-math-smoke-tests
+ SRCS
+ nanf_test.cpp
+ DEPENDS
+ libc.include.math
+ libc.src.math.nanf
+ libc.src.__support.FPUtil.fp_bits
+)
+
+add_fp_unittest(
+ nan_test
+ SUITE
+ libc-math-smoke-tests
+ SRCS
+ nan_test.cpp
+ DEPENDS
+ libc.include.math
+ libc.src.math.nan
+ libc.src.__support.FPUtil.fp_bits
+)
+
+add_fp_unittest(
+ nanl_test
+ SUITE
+ libc-math-smoke-tests
+ SRCS
+ nanl_test.cpp
+ DEPENDS
+ libc.include.math
+ libc.src.math.nanl
+ libc.src.__support.FPUtil.fp_bits
+)
+
# FIXME: These tests are currently spurious for NVPTX.
if(NOT LIBC_GPU_TARGET_ARCHITECTURE_IS_NVPTX)
add_fp_unittest(
diff --git a/libc/test/src/math/smoke/nan_test.cpp b/libc/test/src/math/smoke/nan_test.cpp
new file mode 100644
index 00000000000000..6ff60be92e045b
--- /dev/null
+++ b/libc/test/src/math/smoke/nan_test.cpp
@@ -0,0 +1,40 @@
+//===-- Unittests for nan -------------------------------------------------===//
+//
+// 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/__support/FPUtil/FPBits.h"
+#include "src/math/nan.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+
+class LlvmLibcNanTest : public LIBC_NAMESPACE::testing::Test {
+public:
+ using StorageType = LIBC_NAMESPACE::fputil::FPBits<double>::StorageType;
+
+ void run_test(const char *input_str, StorageType bits) {
+ double result = LIBC_NAMESPACE::nan(input_str);
+ auto actual_fp = LIBC_NAMESPACE::fputil::FPBits<double>(result);
+ auto expected_fp = LIBC_NAMESPACE::fputil::FPBits<double>(bits);
+ EXPECT_EQ(actual_fp.bits, expected_fp.bits);
+ };
+};
+
+TEST_F(LlvmLibcNanTest, NCharSeq) {
+ run_test("", 0x7ff8000000000000);
+ run_test("1234", 0x7ff80000000004d2);
+ run_test("0x1234", 0x7ff8000000001234);
+ run_test("1a", 0x7ff8000000000000);
+ run_test("1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM_",
+ 0x7ff8000000000000);
+}
+
+TEST_F(LlvmLibcNanTest, RandomString) {
+ run_test(" 1234", 0x7ff8000000000000);
+ run_test("-1234", 0x7ff8000000000000);
+ run_test("asd&f", 0x7ff8000000000000);
+ run_test("123 ", 0x7ff8000000000000);
+}
diff --git a/libc/test/src/math/smoke/nanf_test.cpp b/libc/test/src/math/smoke/nanf_test.cpp
new file mode 100644
index 00000000000000..a8ff2f6b019c49
--- /dev/null
+++ b/libc/test/src/math/smoke/nanf_test.cpp
@@ -0,0 +1,40 @@
+//===-- Unittests for nanf ------------------------------------------------===//
+//
+// 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/__support/FPUtil/FPBits.h"
+#include "src/math/nanf.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+
+class LlvmLibcNanfTest : public LIBC_NAMESPACE::testing::Test {
+public:
+ using StorageType = LIBC_NAMESPACE::fputil::FPBits<float>::StorageType;
+
+ void run_test(const char *input_str, StorageType bits) {
+ float result = LIBC_NAMESPACE::nanf(input_str);
+ auto actual_fp = LIBC_NAMESPACE::fputil::FPBits<float>(result);
+ auto expected_fp = LIBC_NAMESPACE::fputil::FPBits<float>(bits);
+ EXPECT_EQ(actual_fp.bits, expected_fp.bits);
+ };
+};
+
+TEST_F(LlvmLibcNanfTest, NCharSeq) {
+ run_test("", 0x7fc00000);
+ run_test("1234", 0x7fc004d2);
+ run_test("0x1234", 0x7fc01234);
+ run_test("1a", 0x7fc00000);
+ run_test("1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM_",
+ 0x7fc00000);
+}
+
+TEST_F(LlvmLibcNanfTest, RandomString) {
+ run_test(" 1234", 0x7fc00000);
+ run_test("-1234", 0x7fc00000);
+ run_test("asd&f", 0x7fc00000);
+ run_test("123 ", 0x7fc00000);
+}
diff --git a/libc/test/src/math/smoke/nanl_test.cpp b/libc/test/src/math/smoke/nanl_test.cpp
new file mode 100644
index 00000000000000..a4283b0dcabc25
--- /dev/null
+++ b/libc/test/src/math/smoke/nanl_test.cpp
@@ -0,0 +1,64 @@
+//===-- Unittests for nanl ------------------------------------------------===//
+//
+// 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/__support/FPUtil/FPBits.h"
+#include "src/math/nanl.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+
+#if defined(LIBC_LONG_DOUBLE_IS_FLOAT64)
+#define SELECT_LONG_DOUBLE(val, _, __) val
+#elif defined(LIBC_LONG_DOUBLE_IS_X86_FLOAT80)
+#define SELECT_LONG_DOUBLE(_, val, __) val
+#else
+#define SELECT_LONG_DOUBLE(_, __, val) val
+#endif
+
+class LlvmLibcNanlTest : public LIBC_NAMESPACE::testing::Test {
+public:
+ using StorageType = LIBC_NAMESPACE::fputil::FPBits<long double>::StorageType;
+
+ void run_test(const char *input_str, StorageType bits) {
+ long double result = LIBC_NAMESPACE::nanl(input_str);
+ auto actual_fp = LIBC_NAMESPACE::fputil::FPBits<long double>(result);
+ auto expected_fp = LIBC_NAMESPACE::fputil::FPBits<long double>(bits);
+ EXPECT_EQ(actual_fp.bits, expected_fp.bits);
+ };
+};
+
+TEST_F(LlvmLibcNanlTest, NCharSeq) {
+ run_test("",
+ SELECT_LONG_DOUBLE(0x7ff8000000000000, (UInt128(0x7fffc00000) << 40),
+ (UInt128(0x7fff800000000000) << 64)));
+ run_test("1234", SELECT_LONG_DOUBLE(
+ 0x7ff80000000004d2,
+ (UInt128(0x7fffc00000) << 40) + UInt128(0x4d2),
+ (UInt128(0x7fff800000000000) << 64) + UInt128(0x4d2)));
+ run_test("0x1234",
+ SELECT_LONG_DOUBLE(0x7ff8000000001234,
+ (UInt128(0x7fffc00000) << 40) + UInt128(0x1234),
+ (UInt128(0x7fff800000000000) << 64) +
+ UInt128(0x1234)));
+ run_test("1a",
+ SELECT_LONG_DOUBLE(0x7ff8000000000000, (UInt128(0x7fffc00000) << 40),
+ (UInt128(0x7fff800000000000) << 64)));
+ run_test("1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM_",
+ SELECT_LONG_DOUBLE(0x7ff8000000000000, (UInt128(0x7fffc00000) << 40),
+ (UInt128(0x7fff800000000000) << 64)));
+}
+
+TEST_F(LlvmLibcNanlTest, RandomString) {
+ StorageType expected =
+ SELECT_LONG_DOUBLE(0x7ff8000000000000, (UInt128(0x7fffc00000) << 40),
+ (UInt128(0x7fff800000000000) << 64));
+
+ run_test(" 1234", expected);
+ run_test("-1234", expected);
+ run_test("asd&f", expected);
+ run_test("123 ", expected);
+}
diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
index b5238f7686e5f4..7d2bb29802552f 100644
--- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
@@ -1874,6 +1874,12 @@ libc_math_function(name = "llroundf")
libc_math_function(name = "llroundl")
+libc_math_function(name = "nan")
+
+libc_math_function(name = "nanf")
+
+libc_math_function(name = "nanl")
+
libc_math_function(name = "nearbyint")
libc_math_function(name = "nearbyintf")
>From 04e2d2ad03ecde12c899b803389e9380a1cedfbc Mon Sep 17 00:00:00 2001
From: Nishant Mittal <nishantwrp at google.com>
Date: Wed, 3 Jan 2024 19:19:41 +0000
Subject: [PATCH 2/5] refactor strtofp to directly use nan handling
---
libc/src/__support/str_to_float.h | 92 +++++++++++++++++--------------
libc/src/math/generic/nan.cpp | 5 +-
libc/src/math/generic/nanf.cpp | 5 +-
libc/src/math/generic/nanl.cpp | 5 +-
4 files changed, 53 insertions(+), 54 deletions(-)
diff --git a/libc/src/__support/str_to_float.h b/libc/src/__support/str_to_float.h
index 555f65707b4e41..d154142c4615b2 100644
--- a/libc/src/__support/str_to_float.h
+++ b/libc/src/__support/str_to_float.h
@@ -1055,6 +1055,38 @@ hexadecimal_string_to_float(const char *__restrict src,
return output;
}
+template <class T>
+LIBC_INLINE fputil::FPBits<T> nan_from_ncharseq(const char *__restrict ncharseq,
+ ptrdiff_t ncharseq_len,
+ int *error, bool sign = false) {
+ using FPBits = typename fputil::FPBits<T>;
+ using StorageType = typename FPBits::StorageType;
+
+ FPBits result = FPBits();
+ StorageType nan_mantissa = 0;
+
+ if (ncharseq != nullptr && isdigit(ncharseq[0])) {
+ // This is to prevent errors when StorageType is larger than 64
+ // bits, since strtointeger only supports up to 64 bits. This is
+ // actually more than is required by the specification, which says
+ // for the input type "NAN(n-char-sequence)" that "the meaning of
+ // the n-char sequence is implementation-defined."
+ auto strtoint_result = strtointeger<uint64_t>(ncharseq, 0);
+ if (strtoint_result.has_error() && error != nullptr)
+ *error = strtoint_result.error;
+
+ nan_mantissa = static_cast<StorageType>(strtoint_result.value);
+ if (strtoint_result.parsed_len != ncharseq_len)
+ nan_mantissa = 0;
+ }
+
+ result = FPBits(result.build_quiet_nan(nan_mantissa));
+ if (sign)
+ result.set_sign(true);
+
+ return result;
+}
+
// Takes a pointer to a string and a pointer to a string pointer. This function
// is used as the backend for all of the string to float functions.
template <class T>
@@ -1134,7 +1166,7 @@ LIBC_INLINE StrToNumResult<T> strtofloatingpoint(const char *__restrict src) {
tolower(src[index + 2]) == nan_string[2]) {
seen_digit = true;
index += 3;
- StorageType nan_mantissa = 0;
+ bool ncharseq_found = false;
// this handles the case of `NaN(n-character-sequence)`, where the
// n-character-sequence is made of 0 or more letters and numbers in any
// order.
@@ -1147,32 +1179,17 @@ LIBC_INLINE StrToNumResult<T> strtofloatingpoint(const char *__restrict src) {
++index;
if (src[index] == ')') {
++index;
- if (isdigit(src[left_paren + 1])) {
- // This is to prevent errors when StorageType is larger than 64
- // bits, since strtointeger only supports up to 64 bits. This is
- // actually more than is required by the specification, which says
- // for the input type "NAN(n-char-sequence)" that "the meaning of
- // the n-char sequence is implementation-defined."
-
- auto strtoint_result =
- strtointeger<uint64_t>(src + (left_paren + 1), 0);
- if (strtoint_result.has_error()) {
- error = strtoint_result.error;
- }
- nan_mantissa = static_cast<StorageType>(strtoint_result.value);
- if (src[left_paren + 1 + strtoint_result.parsed_len] != ')')
- nan_mantissa = 0;
- }
+ result = nan_from_ncharseq<T>(src + (left_paren + 1),
+ index - left_paren - 2, &error,
+ result.get_sign());
+ ncharseq_found = true;
} else {
index = left_paren;
}
}
- if (result.get_sign()) {
- result = FPBits(result.build_quiet_nan(nan_mantissa));
- result.set_sign(true);
- } else {
- result.set_sign(false);
- result = FPBits(result.build_quiet_nan(nan_mantissa));
+
+ if (!ncharseq_found) {
+ result = nan_from_ncharseq<T>(nullptr, 0, &error, result.get_sign());
}
}
} else if (tolower(src[index]) == 'i') { // INF
@@ -1206,32 +1223,23 @@ LIBC_INLINE StrToNumResult<T> strtofloatingpoint(const char *__restrict src) {
return {T(result), index, error};
}
-LIBC_INLINE const char *nan_str_to_floatingpoint_str(const char *arg) {
+template <class T> LIBC_INLINE StrToNumResult<T> strtonan(const char *arg) {
+ using FPBits = typename fputil::FPBits<T>;
+
+ FPBits result;
+ int error = 0;
+
ptrdiff_t index = 0;
while (isalnum(arg[index]) || arg[index] == '_')
++index;
if (arg[index] == '\0') {
- // 5 is the number of characters in string "NAN()".
- ptrdiff_t size = 5 + index;
- char *output_str = new char[size + 1];
-
- output_str[0] = 'N';
- output_str[1] = 'A';
- output_str[2] = 'N';
- output_str[3] = '(';
-
- for (ptrdiff_t i = 0; i < index; ++i) {
- output_str[4 + i] = arg[i];
- }
-
- output_str[size - 1] = ')';
- output_str[size] = '\0';
-
- return output_str;
+ result = nan_from_ncharseq<T>(arg, index, &error);
+ return {T(result), index, error};
}
- return "NAN";
+ result = nan_from_ncharseq<T>(nullptr, 0, &error);
+ return {T(result), 0, error};
}
} // namespace internal
diff --git a/libc/src/math/generic/nan.cpp b/libc/src/math/generic/nan.cpp
index 9d591dcd3d091b..c0d7fbf4ba4833 100644
--- a/libc/src/math/generic/nan.cpp
+++ b/libc/src/math/generic/nan.cpp
@@ -14,12 +14,9 @@
namespace LIBC_NAMESPACE {
LLVM_LIBC_FUNCTION(double, nan, (const char *arg)) {
- const char *fp_str = internal::nan_str_to_floatingpoint_str(arg);
- auto result = internal::strtofloatingpoint<double>(fp_str);
-
+ auto result = internal::strtonan<double>(arg);
if (result.has_error())
libc_errno = result.error;
-
return result.value;
}
diff --git a/libc/src/math/generic/nanf.cpp b/libc/src/math/generic/nanf.cpp
index b83e715485e471..2751a81ac46192 100644
--- a/libc/src/math/generic/nanf.cpp
+++ b/libc/src/math/generic/nanf.cpp
@@ -14,12 +14,9 @@
namespace LIBC_NAMESPACE {
LLVM_LIBC_FUNCTION(float, nanf, (const char *arg)) {
- const char *fp_str = internal::nan_str_to_floatingpoint_str(arg);
- auto result = internal::strtofloatingpoint<float>(fp_str);
-
+ auto result = internal::strtonan<float>(arg);
if (result.has_error())
libc_errno = result.error;
-
return result.value;
}
diff --git a/libc/src/math/generic/nanl.cpp b/libc/src/math/generic/nanl.cpp
index 6f70af9957b426..76dcb56b47b2d9 100644
--- a/libc/src/math/generic/nanl.cpp
+++ b/libc/src/math/generic/nanl.cpp
@@ -14,12 +14,9 @@
namespace LIBC_NAMESPACE {
LLVM_LIBC_FUNCTION(long double, nanl, (const char *arg)) {
- const char *fp_str = internal::nan_str_to_floatingpoint_str(arg);
- auto result = internal::strtofloatingpoint<long double>(fp_str);
-
+ auto result = internal::strtonan<long double>(arg);
if (result.has_error())
libc_errno = result.error;
-
return result.value;
}
>From c83ba2ac71020cb3e1010bee0069140fd54410cf Mon Sep 17 00:00:00 2001
From: Nishant Mittal <nishantwrp at google.com>
Date: Wed, 3 Jan 2024 20:52:40 +0000
Subject: [PATCH 3/5] make util function simpler
---
libc/src/__support/str_to_float.h | 47 +++++++++++++++----------------
1 file changed, 22 insertions(+), 25 deletions(-)
diff --git a/libc/src/__support/str_to_float.h b/libc/src/__support/str_to_float.h
index d154142c4615b2..12f6a0e3d4f28b 100644
--- a/libc/src/__support/str_to_float.h
+++ b/libc/src/__support/str_to_float.h
@@ -12,6 +12,7 @@
#include "src/__support/CPP/bit.h"
#include "src/__support/CPP/limits.h"
#include "src/__support/CPP/optional.h"
+#include "src/__support/CPP/string_view.h"
#include "src/__support/FPUtil/FEnvImpl.h"
#include "src/__support/FPUtil/FPBits.h"
#include "src/__support/FPUtil/dyadic_float.h"
@@ -1056,35 +1057,27 @@ hexadecimal_string_to_float(const char *__restrict src,
}
template <class T>
-LIBC_INLINE fputil::FPBits<T> nan_from_ncharseq(const char *__restrict ncharseq,
- ptrdiff_t ncharseq_len,
- int *error, bool sign = false) {
- using FPBits = typename fputil::FPBits<T>;
- using StorageType = typename FPBits::StorageType;
-
- FPBits result = FPBits();
+LIBC_INLINE typename fputil::FPBits<T>::StorageType
+nan_mantissa_from_ncharseq(const cpp::string_view ncharseq, int *error) {
+ using StorageType = typename fputil::FPBits<T>::StorageType;
StorageType nan_mantissa = 0;
- if (ncharseq != nullptr && isdigit(ncharseq[0])) {
+ if (ncharseq.data() != nullptr && isdigit(*ncharseq.data())) {
// This is to prevent errors when StorageType is larger than 64
// bits, since strtointeger only supports up to 64 bits. This is
// actually more than is required by the specification, which says
// for the input type "NAN(n-char-sequence)" that "the meaning of
// the n-char sequence is implementation-defined."
- auto strtoint_result = strtointeger<uint64_t>(ncharseq, 0);
+ auto strtoint_result = strtointeger<uint64_t>(ncharseq.data(), 0);
if (strtoint_result.has_error() && error != nullptr)
*error = strtoint_result.error;
nan_mantissa = static_cast<StorageType>(strtoint_result.value);
- if (strtoint_result.parsed_len != ncharseq_len)
+ if (strtoint_result.parsed_len != (ptrdiff_t)ncharseq.size())
nan_mantissa = 0;
}
- result = FPBits(result.build_quiet_nan(nan_mantissa));
- if (sign)
- result.set_sign(true);
-
- return result;
+ return nan_mantissa;
}
// Takes a pointer to a string and a pointer to a string pointer. This function
@@ -1166,7 +1159,7 @@ LIBC_INLINE StrToNumResult<T> strtofloatingpoint(const char *__restrict src) {
tolower(src[index + 2]) == nan_string[2]) {
seen_digit = true;
index += 3;
- bool ncharseq_found = false;
+ StorageType nan_mantissa = 0;
// this handles the case of `NaN(n-character-sequence)`, where the
// n-character-sequence is made of 0 or more letters and numbers in any
// order.
@@ -1179,17 +1172,19 @@ LIBC_INLINE StrToNumResult<T> strtofloatingpoint(const char *__restrict src) {
++index;
if (src[index] == ')') {
++index;
- result = nan_from_ncharseq<T>(src + (left_paren + 1),
- index - left_paren - 2, &error,
- result.get_sign());
- ncharseq_found = true;
+ nan_mantissa = nan_mantissa_from_ncharseq<T>(
+ cpp::string_view(src + (left_paren + 1), index - left_paren - 2),
+ &error);
} else {
index = left_paren;
}
}
- if (!ncharseq_found) {
- result = nan_from_ncharseq<T>(nullptr, 0, &error, result.get_sign());
+ if (result.get_sign()) {
+ result = FPBits(result.build_quiet_nan(nan_mantissa));
+ result.set_sign(true);
+ } else {
+ result = FPBits(result.build_quiet_nan(nan_mantissa));
}
}
} else if (tolower(src[index]) == 'i') { // INF
@@ -1225,20 +1220,22 @@ LIBC_INLINE StrToNumResult<T> strtofloatingpoint(const char *__restrict src) {
template <class T> LIBC_INLINE StrToNumResult<T> strtonan(const char *arg) {
using FPBits = typename fputil::FPBits<T>;
+ using StorageType = typename FPBits::StorageType;
FPBits result;
int error = 0;
+ StorageType nan_mantissa = 0;
ptrdiff_t index = 0;
while (isalnum(arg[index]) || arg[index] == '_')
++index;
if (arg[index] == '\0') {
- result = nan_from_ncharseq<T>(arg, index, &error);
- return {T(result), index, error};
+ nan_mantissa =
+ nan_mantissa_from_ncharseq<T>(cpp::string_view(arg, index), &error);
}
- result = nan_from_ncharseq<T>(nullptr, 0, &error);
+ result = FPBits(result.build_quiet_nan(nan_mantissa));
return {T(result), 0, error};
}
>From 47dd20460d1c31c8aaa1667442c8cd7274fb2e26 Mon Sep 17 00:00:00 2001
From: Nishant Mittal <nishantwrp at google.com>
Date: Thu, 4 Jan 2024 07:35:28 +0000
Subject: [PATCH 4/5] Move error to result
---
libc/src/__support/str_to_float.h | 38 +++++++++++++++++++------------
1 file changed, 24 insertions(+), 14 deletions(-)
diff --git a/libc/src/__support/str_to_float.h b/libc/src/__support/str_to_float.h
index 12f6a0e3d4f28b..dca062a6d1f928 100644
--- a/libc/src/__support/str_to_float.h
+++ b/libc/src/__support/str_to_float.h
@@ -1056,11 +1056,18 @@ hexadecimal_string_to_float(const char *__restrict src,
return output;
}
-template <class T>
-LIBC_INLINE typename fputil::FPBits<T>::StorageType
-nan_mantissa_from_ncharseq(const cpp::string_view ncharseq, int *error) {
- using StorageType = typename fputil::FPBits<T>::StorageType;
- StorageType nan_mantissa = 0;
+struct NanMantissaResult {
+ uint64_t value;
+ int error;
+
+ LIBC_INLINE constexpr NanMantissaResult(uint64_t value, int error)
+ : value(value), error(0) {}
+};
+
+LIBC_INLINE NanMantissaResult
+nan_mantissa_from_ncharseq(const cpp::string_view ncharseq) {
+ uint64_t nan_mantissa = 0;
+ int error = 0;
if (ncharseq.data() != nullptr && isdigit(*ncharseq.data())) {
// This is to prevent errors when StorageType is larger than 64
@@ -1069,15 +1076,15 @@ nan_mantissa_from_ncharseq(const cpp::string_view ncharseq, int *error) {
// for the input type "NAN(n-char-sequence)" that "the meaning of
// the n-char sequence is implementation-defined."
auto strtoint_result = strtointeger<uint64_t>(ncharseq.data(), 0);
- if (strtoint_result.has_error() && error != nullptr)
- *error = strtoint_result.error;
+ if (strtoint_result.has_error())
+ error = strtoint_result.error;
- nan_mantissa = static_cast<StorageType>(strtoint_result.value);
+ nan_mantissa = strtoint_result.value;
if (strtoint_result.parsed_len != (ptrdiff_t)ncharseq.size())
nan_mantissa = 0;
}
- return nan_mantissa;
+ return NanMantissaResult(nan_mantissa, error);
}
// Takes a pointer to a string and a pointer to a string pointer. This function
@@ -1172,9 +1179,10 @@ LIBC_INLINE StrToNumResult<T> strtofloatingpoint(const char *__restrict src) {
++index;
if (src[index] == ')') {
++index;
- nan_mantissa = nan_mantissa_from_ncharseq<T>(
- cpp::string_view(src + (left_paren + 1), index - left_paren - 2),
- &error);
+ auto nan_mantissa_result = nan_mantissa_from_ncharseq(
+ cpp::string_view(src + (left_paren + 1), index - left_paren - 2));
+ nan_mantissa = static_cast<StorageType>(nan_mantissa_result.value);
+ error = nan_mantissa_result.error;
} else {
index = left_paren;
}
@@ -1231,8 +1239,10 @@ template <class T> LIBC_INLINE StrToNumResult<T> strtonan(const char *arg) {
++index;
if (arg[index] == '\0') {
- nan_mantissa =
- nan_mantissa_from_ncharseq<T>(cpp::string_view(arg, index), &error);
+ auto nan_mantissa_result =
+ nan_mantissa_from_ncharseq(cpp::string_view(arg, index));
+ nan_mantissa = static_cast<StorageType>(nan_mantissa_result.value);
+ error = nan_mantissa_result.error;
}
result = FPBits(result.build_quiet_nan(nan_mantissa));
>From 29519d5e9862a439360fe701f6e362ecfad9c2a7 Mon Sep 17 00:00:00 2001
From: Nishant Mittal <nishantwrp at google.com>
Date: Thu, 4 Jan 2024 07:55:27 +0000
Subject: [PATCH 5/5] add death tests for nullptr
---
libc/test/src/math/smoke/CMakeLists.txt | 3 +++
libc/test/src/math/smoke/nan_test.cpp | 5 +++++
libc/test/src/math/smoke/nanf_test.cpp | 5 +++++
libc/test/src/math/smoke/nanl_test.cpp | 5 +++++
4 files changed, 18 insertions(+)
diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt
index 6488f9f86f1fd3..65dc80c2a882a5 100644
--- a/libc/test/src/math/smoke/CMakeLists.txt
+++ b/libc/test/src/math/smoke/CMakeLists.txt
@@ -1211,6 +1211,7 @@ add_fp_unittest(
nanf_test.cpp
DEPENDS
libc.include.math
+ libc.include.signal
libc.src.math.nanf
libc.src.__support.FPUtil.fp_bits
)
@@ -1223,6 +1224,7 @@ add_fp_unittest(
nan_test.cpp
DEPENDS
libc.include.math
+ libc.include.signal
libc.src.math.nan
libc.src.__support.FPUtil.fp_bits
)
@@ -1235,6 +1237,7 @@ add_fp_unittest(
nanl_test.cpp
DEPENDS
libc.include.math
+ libc.include.signal
libc.src.math.nanl
libc.src.__support.FPUtil.fp_bits
)
diff --git a/libc/test/src/math/smoke/nan_test.cpp b/libc/test/src/math/smoke/nan_test.cpp
index 6ff60be92e045b..cb044787c11870 100644
--- a/libc/test/src/math/smoke/nan_test.cpp
+++ b/libc/test/src/math/smoke/nan_test.cpp
@@ -10,6 +10,7 @@
#include "src/math/nan.h"
#include "test/UnitTest/FPMatcher.h"
#include "test/UnitTest/Test.h"
+#include <signal.h>
class LlvmLibcNanTest : public LIBC_NAMESPACE::testing::Test {
public:
@@ -38,3 +39,7 @@ TEST_F(LlvmLibcNanTest, RandomString) {
run_test("asd&f", 0x7ff8000000000000);
run_test("123 ", 0x7ff8000000000000);
}
+
+TEST_F(LlvmLibcNanTest, InvalidInput) {
+ EXPECT_DEATH([] { LIBC_NAMESPACE::nan(nullptr); }, WITH_SIGNAL(SIGSEGV));
+}
diff --git a/libc/test/src/math/smoke/nanf_test.cpp b/libc/test/src/math/smoke/nanf_test.cpp
index a8ff2f6b019c49..ba70fe4f31407e 100644
--- a/libc/test/src/math/smoke/nanf_test.cpp
+++ b/libc/test/src/math/smoke/nanf_test.cpp
@@ -10,6 +10,7 @@
#include "src/math/nanf.h"
#include "test/UnitTest/FPMatcher.h"
#include "test/UnitTest/Test.h"
+#include <signal.h>
class LlvmLibcNanfTest : public LIBC_NAMESPACE::testing::Test {
public:
@@ -38,3 +39,7 @@ TEST_F(LlvmLibcNanfTest, RandomString) {
run_test("asd&f", 0x7fc00000);
run_test("123 ", 0x7fc00000);
}
+
+TEST_F(LlvmLibcNanfTest, InvalidInput) {
+ EXPECT_DEATH([] { LIBC_NAMESPACE::nanf(nullptr); }, WITH_SIGNAL(SIGSEGV));
+}
diff --git a/libc/test/src/math/smoke/nanl_test.cpp b/libc/test/src/math/smoke/nanl_test.cpp
index a4283b0dcabc25..1528d14faa36e2 100644
--- a/libc/test/src/math/smoke/nanl_test.cpp
+++ b/libc/test/src/math/smoke/nanl_test.cpp
@@ -10,6 +10,7 @@
#include "src/math/nanl.h"
#include "test/UnitTest/FPMatcher.h"
#include "test/UnitTest/Test.h"
+#include <signal.h>
#if defined(LIBC_LONG_DOUBLE_IS_FLOAT64)
#define SELECT_LONG_DOUBLE(val, _, __) val
@@ -62,3 +63,7 @@ TEST_F(LlvmLibcNanlTest, RandomString) {
run_test("asd&f", expected);
run_test("123 ", expected);
}
+
+TEST_F(LlvmLibcNanlTest, InvalidInput) {
+ EXPECT_DEATH([] { LIBC_NAMESPACE::nanl(nullptr); }, WITH_SIGNAL(SIGSEGV));
+}
More information about the libc-commits
mailing list