diff --git a/libc/config/linux/aarch64/headers.txt b/libc/config/linux/aarch64/headers.txt index 1725f9c2e75fa..21b880cf2bb9b 100644 --- a/libc/config/linux/aarch64/headers.txt +++ b/libc/config/linux/aarch64/headers.txt @@ -10,6 +10,7 @@ set(TARGET_PUBLIC_HEADERS libc.include.math libc.include.pthread libc.include.signal + libc.include.stdckdint libc.include.stdbit libc.include.stdio libc.include.stdlib diff --git a/libc/config/linux/arm/headers.txt b/libc/config/linux/arm/headers.txt index c482371944361..268c8c41702af 100644 --- a/libc/config/linux/arm/headers.txt +++ b/libc/config/linux/arm/headers.txt @@ -5,6 +5,7 @@ set(TARGET_PUBLIC_HEADERS libc.include.float libc.include.inttypes libc.include.math + libc.include.stdckdint libc.include.stdbit libc.include.stdlib libc.include.string diff --git a/libc/config/linux/riscv/headers.txt b/libc/config/linux/riscv/headers.txt index 5e8af22158748..3ebea2e2b07bf 100644 --- a/libc/config/linux/riscv/headers.txt +++ b/libc/config/linux/riscv/headers.txt @@ -15,6 +15,7 @@ set(TARGET_PUBLIC_HEADERS libc.include.signal libc.include.spawn libc.include.setjmp + libc.include.stdckdint libc.include.stdbit libc.include.stdio libc.include.stdlib diff --git a/libc/config/linux/x86_64/headers.txt b/libc/config/linux/x86_64/headers.txt index d0c662c2bc072..a887eba6805bc 100644 --- a/libc/config/linux/x86_64/headers.txt +++ b/libc/config/linux/x86_64/headers.txt @@ -15,6 +15,7 @@ set(TARGET_PUBLIC_HEADERS libc.include.signal libc.include.spawn libc.include.setjmp + libc.include.stdckdint libc.include.stdbit libc.include.stdfix libc.include.stdio diff --git a/libc/docs/c23.rst b/libc/docs/c23.rst index 6d5edbfbf5e71..ec9d40947cc56 100644 --- a/libc/docs/c23.rst +++ b/libc/docs/c23.rst @@ -4,6 +4,7 @@ C23 Support =========== +.. include:: check.rst .. contents:: Table of Contents :depth: 4 :local: @@ -17,7 +18,7 @@ Implementation Status New headers: * stdbit.h -* stdckdint.h +* stdckdint.h (|check|, macros are only defined with `__GNUC__` builtins) Additions: diff --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt index 5882d03593a54..dc3c9b8e6328a 100644 --- a/libc/include/CMakeLists.txt +++ b/libc/include/CMakeLists.txt @@ -242,6 +242,15 @@ add_gen_header( .llvm-libc-macros.stdbit_macros ) +add_gen_header( + stdckdint + DEF_FILE stdckdint.h.def + GEN_HDR stdckdint.h + DEPENDS + .llvm_libc_common_h + .llvm-libc-macros.stdckdint_macros +) + add_gen_header( stdio DEF_FILE stdio.h.def diff --git a/libc/include/llvm-libc-macros/CMakeLists.txt b/libc/include/llvm-libc-macros/CMakeLists.txt index 225885d3a9b08..6e0875829127e 100644 --- a/libc/include/llvm-libc-macros/CMakeLists.txt +++ b/libc/include/llvm-libc-macros/CMakeLists.txt @@ -233,3 +233,9 @@ add_macro_header( HDR stdfix-macros.h ) + +add_macro_header( + stdckdint_macros + HDR + stdckdint-macros.h +) diff --git a/libc/include/llvm-libc-macros/stdckdint-macros.h b/libc/include/llvm-libc-macros/stdckdint-macros.h new file mode 100644 index 0000000000000..03b73aeeb6710 --- /dev/null +++ b/libc/include/llvm-libc-macros/stdckdint-macros.h @@ -0,0 +1,25 @@ +//===-- Definition of macros for stdckdint.h ------------------------------===// +// +// 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_MACROS_STDCKDINT_MACROS_H +#define __LLVM_LIBC_MACROS_STDCKDINT_MACROS_H + +// We need to use __builtin_*_overflow from GCC/Clang to implement the overflow +// macros. Check __GNUC__ for availability of such builtins. +#ifdef __GNUC__ +// clang/gcc overlay may provides similar macros, we need to avoid redefining +// them. +#ifndef __STDC_VERSION_STDCKDINT_H__ +#define __STDC_VERSION_STDCKDINT_H__ 202311L + +#define ckd_add(R, A, B) __builtin_add_overflow((A), (B), (R)) +#define ckd_sub(R, A, B) __builtin_sub_overflow((A), (B), (R)) +#define ckd_mul(R, A, B) __builtin_mul_overflow((A), (B), (R)) +#endif // __STDC_VERSION_STDCKDINT_H__ +#endif // __GNUC__ +#endif // __LLVM_LIBC_MACROS_STDCKDINT_MACROS_H diff --git a/libc/include/stdckdint.h.def b/libc/include/stdckdint.h.def new file mode 100644 index 0000000000000..c82470911c33f --- /dev/null +++ b/libc/include/stdckdint.h.def @@ -0,0 +1,18 @@ +//===-- C standard library header stdckdint.h -----------------------------===// +// +// 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_STDCKDINT_H +#define LLVM_LIBC_STDCKDINT_H + +#include <__llvm-libc-common.h> + +%%public_api() + +#include + +#endif // LLVM_LIBC_STDCKDINT_H diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td index 5fdcec7dbbdfc..3fe19fae4c2e5 100644 --- a/libc/spec/stdc.td +++ b/libc/spec/stdc.td @@ -833,6 +833,19 @@ def StdC : StandardSpec<"stdc"> { ] // Functions >; + HeaderSpec StdCkdInt = HeaderSpec< + "stdckdint.h", + [ + Macro<"__STDC_VERSION_STDCKDINT_H__">, + Macro<"ckd_add">, + Macro<"ckd_sub">, + Macro<"ckd_mul"> + ], // Macros + [], // Types + [], // Enumerations + [] // Functions + >; + HeaderSpec StdLib = HeaderSpec< "stdlib.h", [], // Macros @@ -1234,6 +1247,7 @@ def StdC : StandardSpec<"stdc"> { Math, String, StdBit, + StdCkdInt, StdIO, StdLib, IntTypes, diff --git a/libc/src/stdckdint/CMakeLists.txt b/libc/src/stdckdint/CMakeLists.txt new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/libc/test/include/CMakeLists.txt b/libc/test/include/CMakeLists.txt index 2730fa0d66db7..bf845c94170f9 100644 --- a/libc/test/include/CMakeLists.txt +++ b/libc/test/include/CMakeLists.txt @@ -33,3 +33,13 @@ if(LLVM_LIBC_FULL_BUILD AND libc.include.stdbit IN_LIST TARGET_PUBLIC_HEADERS) # to. ) endif() + +add_libc_test( + stdckdint_test + SUITE + libc_include_tests + SRCS + stdckdint_test.cpp + DEPENDS + libc.include.llvm-libc-macros.stdckdint_macros +) diff --git a/libc/test/include/stdckdint_test.cpp b/libc/test/include/stdckdint_test.cpp new file mode 100644 index 0000000000000..1180a6de9efe2 --- /dev/null +++ b/libc/test/include/stdckdint_test.cpp @@ -0,0 +1,32 @@ +//===-- Unittests for stdckdint -------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDSList-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "test/UnitTest/Test.h" + +#include "include/llvm-libc-macros/stdckdint-macros.h" + +TEST(LlvmLibcStdCkdIntTest, Add) { + int result; + ASSERT_FALSE(ckd_add(&result, 1, 2)); + ASSERT_EQ(result, 3); + ASSERT_TRUE(ckd_add(&result, INT_MAX, 1)); +} + +TEST(LlvmLibcStdCkdIntTest, Sub) { + int result; + ASSERT_FALSE(ckd_sub(&result, 3, 2)); + ASSERT_EQ(result, 1); + ASSERT_TRUE(ckd_sub(&result, INT_MIN, 1)); +} + +TEST(LlvmLibcStdCkdIntTest, Mul) { + int result; + ASSERT_FALSE(ckd_mul(&result, 2, 3)); + ASSERT_EQ(result, 6); + ASSERT_TRUE(ckd_mul(&result, INT_MAX, 2)); +}