[clang] 3694697 - [clang] Implement C23 <stdckdint.h>

via cfe-commits cfe-commits at lists.llvm.org
Mon Oct 16 17:52:04 PDT 2023


Author: zijunzhao
Date: 2023-10-17T00:51:21Z
New Revision: 3694697003bbf443fd644c6746a1c7c937657fce

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

LOG: [clang] Implement C23 <stdckdint.h>

https://github.com/llvm/llvm-project/issues/62248

Reviewed By: yabinc, aaron.ballman, #clang-language-wg

Differential Revision: https://reviews.llvm.org/D157331

Added: 
    clang/lib/Headers/stdckdint.h
    clang/test/C/C2x/n2683.c
    clang/test/C/C2x/n2683_2.c
    clang/test/Headers/stdckdint.c

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/include/clang/Basic/DiagnosticSemaKinds.td
    clang/lib/Headers/CMakeLists.txt
    clang/lib/Lex/PPDirectives.cpp
    clang/lib/Sema/SemaChecking.cpp
    clang/test/C/C2x/n2359.c
    clang/test/Sema/builtins-overflow.c
    clang/www/c_status.html

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index ff66d2c272098c8..3f83cd71e64cbce 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -176,6 +176,9 @@ C23 Feature Support
 - Clang now supports `requires c23` for module maps.
 - Clang now supports ``N3007 Type inference for object definitions``.
 
+- Clang now supports ``<stdckdint.h>`` which defines several macros for performing
+  checked integer arithmetic.
+
 Non-comprehensive list of changes in this release
 -------------------------------------------------
 

diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index e85cd4d1a1ddc0d..58a33e2807b7b0a 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -8690,10 +8690,13 @@ def warn_atomic_implicit_seq_cst : Warning<
   InGroup<DiagGroup<"atomic-implicit-seq-cst">>, DefaultIgnore;
 
 def err_overflow_builtin_must_be_int : Error<
-  "operand argument to overflow builtin must be an integer (%0 invalid)">;
+  "operand argument to %select{overflow builtin|checked integer operation}0 "
+  "must be an integer type %select{|other than plain 'char', 'bool', bit-precise, "
+  "or an enumeration }0(%1 invalid)">;
 def err_overflow_builtin_must_be_ptr_int : Error<
-  "result argument to overflow builtin must be a pointer "
-  "to a non-const integer (%0 invalid)">;
+  "result argument to %select{overflow builtin|checked integer operation}0 "
+  "must be a pointer to a non-const integer type %select{|other than plain 'char', "
+  "'bool', bit-precise, or an enumeration }0(%1 invalid)">;
 def err_overflow_builtin_bit_int_max_size : Error<
   "__builtin_mul_overflow does not support 'signed _BitInt' operands of more "
   "than %0 bits">;

diff  --git a/clang/lib/Headers/CMakeLists.txt b/clang/lib/Headers/CMakeLists.txt
index 3b6fec3da2b16ff..02a0c81644b6c6d 100644
--- a/clang/lib/Headers/CMakeLists.txt
+++ b/clang/lib/Headers/CMakeLists.txt
@@ -17,6 +17,7 @@ set(core_files
   __stdarg_va_list.h
   stdatomic.h
   stdbool.h
+  stdckdint.h
   stddef.h
   __stddef_max_align_t.h
   __stddef_null.h

diff  --git a/clang/lib/Headers/stdckdint.h b/clang/lib/Headers/stdckdint.h
new file mode 100644
index 000000000000000..22972d78d9077a4
--- /dev/null
+++ b/clang/lib/Headers/stdckdint.h
@@ -0,0 +1,44 @@
+/*===---- stdckdint.h - Standard header for checking integer----------------===
+ *
+ * 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 __STDCKDINT_H
+#define __STDCKDINT_H
+
+/* If we're hosted, fall back to the system's stdckdint.h. FreeBSD, for
+ * example, already has a Clang-compatible stdckdint.h header.
+ *
+ * The `stdckdint.h` header requires C 23 or newer.
+ */
+#if __STDC_HOSTED__ && __has_include_next(<stdckdint.h>)
+#include_next <stdckdint.h>
+#else
+
+/* C23 7.20.1 Defines several macros for performing checked integer arithmetic*/
+
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L
+#define __STDC_VERSION_STDCKDINT_H__ 202311L
+
+// Both A and B shall be any integer type other than "plain" char, bool, a bit-
+// precise integer type, or an enumerated type, and they need not be the same.
+
+// R shall be a modifiable lvalue of any integer type other than "plain" char,
+// bool, a bit-precise integer type, or an enumerated type. It shouldn't be
+// short type, either. Otherwise, it may be unable to hold two the result of
+// operating two 'int's.
+
+// A diagnostic message will be produced if A or B are not suitable integer
+// types, or if R is not a modifiable lvalue of a suitable integer type or R
+// is short type.
+#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
+
+#endif /* __STDC_HOSTED__ */
+#endif /* __STDCKDINT_H */

diff  --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp
index e3065c17dc70b43..2892d4b777846ff 100644
--- a/clang/lib/Lex/PPDirectives.cpp
+++ b/clang/lib/Lex/PPDirectives.cpp
@@ -231,9 +231,10 @@ static bool warnByDefaultOnWrongCase(StringRef Include) {
     .Cases("assert.h", "complex.h", "ctype.h", "errno.h", "fenv.h", true)
     .Cases("float.h", "inttypes.h", "iso646.h", "limits.h", "locale.h", true)
     .Cases("math.h", "setjmp.h", "signal.h", "stdalign.h", "stdarg.h", true)
-    .Cases("stdatomic.h", "stdbool.h", "stddef.h", "stdint.h", "stdio.h", true)
-    .Cases("stdlib.h", "stdnoreturn.h", "string.h", "tgmath.h", "threads.h", true)
-    .Cases("time.h", "uchar.h", "wchar.h", "wctype.h", true)
+    .Cases("stdatomic.h", "stdbool.h", "stdckdint.h", "stddef.h", true)
+    .Cases("stdint.h", "stdio.h", "stdlib.h", "stdnoreturn.h", true)
+    .Cases("string.h", "tgmath.h", "threads.h", "time.h", "uchar.h", true)
+    .Cases("wchar.h", "wctype.h", true)
 
     // C++ headers for C library facilities
     .Cases("cassert", "ccomplex", "cctype", "cerrno", "cfenv", true)

diff  --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 35b36db2049db09..e121da8fac6d9b4 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -370,6 +370,32 @@ static bool SemaBuiltinOverflow(Sema &S, CallExpr *TheCall,
   if (checkArgCount(S, TheCall, 3))
     return true;
 
+  std::pair<unsigned, const char *> Builtins[] = {
+    { Builtin::BI__builtin_add_overflow, "ckd_add" },
+    { Builtin::BI__builtin_sub_overflow, "ckd_sub" },
+    { Builtin::BI__builtin_mul_overflow, "ckd_mul" },
+  };
+
+  bool CkdOperation = llvm::any_of(Builtins, [&](const std::pair<unsigned,
+    const char *> &P) {
+    return BuiltinID == P.first && TheCall->getExprLoc().isMacroID() &&
+         Lexer::getImmediateMacroName(TheCall->getExprLoc(),
+         S.getSourceManager(), S.getLangOpts()) == P.second;
+  });
+
+  auto ValidCkdIntType = [](QualType QT) {
+    // A valid checked integer type is an integer type other than a plain char,
+    // bool, a bit-precise type, or an enumeration type.
+    if (const auto *BT = QT.getCanonicalType()->getAs<BuiltinType>())
+      return (BT->getKind() >= BuiltinType::Short &&
+           BT->getKind() <= BuiltinType::Int128) || (
+           BT->getKind() >= BuiltinType::UShort &&
+           BT->getKind() <= BuiltinType::UInt128) ||
+           BT->getKind() == BuiltinType::UChar ||
+           BT->getKind() == BuiltinType::SChar;
+    return false;
+  };
+
   // First two arguments should be integers.
   for (unsigned I = 0; I < 2; ++I) {
     ExprResult Arg = S.DefaultFunctionArrayLvalueConversion(TheCall->getArg(I));
@@ -377,9 +403,10 @@ static bool SemaBuiltinOverflow(Sema &S, CallExpr *TheCall,
     TheCall->setArg(I, Arg.get());
 
     QualType Ty = Arg.get()->getType();
-    if (!Ty->isIntegerType()) {
+    bool IsValid = CkdOperation ? ValidCkdIntType(Ty) : Ty->isIntegerType();
+    if (!IsValid) {
       S.Diag(Arg.get()->getBeginLoc(), diag::err_overflow_builtin_must_be_int)
-          << Ty << Arg.get()->getSourceRange();
+          << CkdOperation << Ty << Arg.get()->getSourceRange();
       return true;
     }
   }
@@ -396,10 +423,11 @@ static bool SemaBuiltinOverflow(Sema &S, CallExpr *TheCall,
     const auto *PtrTy = Ty->getAs<PointerType>();
     if (!PtrTy ||
         !PtrTy->getPointeeType()->isIntegerType() ||
+        (!ValidCkdIntType(PtrTy->getPointeeType()) && CkdOperation) ||
         PtrTy->getPointeeType().isConstQualified()) {
       S.Diag(Arg.get()->getBeginLoc(),
              diag::err_overflow_builtin_must_be_ptr_int)
-        << Ty << Arg.get()->getSourceRange();
+        << CkdOperation << Ty << Arg.get()->getSourceRange();
       return true;
     }
   }

diff  --git a/clang/test/C/C2x/n2359.c b/clang/test/C/C2x/n2359.c
index 3a6641fbeaede28..dc38bab43c9db8d 100644
--- a/clang/test/C/C2x/n2359.c
+++ b/clang/test/C/C2x/n2359.c
@@ -34,3 +34,7 @@
 // expected-error at -1 {{"__STDC_VERSION_STDINT_H__ not defined"}}
 #endif
 
+#include <stdckdint.h>
+#ifndef __STDC_VERSION_STDCKDINT_H__
+#error "__STDC_VERSION_STDCKDINT_H__ not defined"
+#endif

diff  --git a/clang/test/C/C2x/n2683.c b/clang/test/C/C2x/n2683.c
new file mode 100644
index 000000000000000..0c666c5fd8782ba
--- /dev/null
+++ b/clang/test/C/C2x/n2683.c
@@ -0,0 +1,51 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 3
+// RUN: %clang_cc1 -triple=x86_64 -verify -ffreestanding -std=c23 %s
+
+/* WG14 N2683: Clang 18
+ * Towards Integer Safety
+ */
+#include <stdckdint.h>
+#include <stddef.h>
+#include <stdint.h>
+
+void test_semantic() {
+  int64_t result64 = 0;
+  int32_t result32 = 0;
+  wchar_t wide_char = L'A'; // The ascii value of `A` is 65
+
+  bool flag_add = ckd_add(&result64, INT32_MAX, 1);
+  bool flag_sub = ckd_sub(&result32, INT32_MAX, -1);
+  bool flag_mul = ckd_mul(&result64, INT64_MAX, 1);
+
+  bool flag = ckd_add(&result64, wide_char, result32); // In C, wchar_t is a typedef to some integer type and is allowed.
+
+  // FIXME: add static_assert calls to check the resulting values for correctness
+  // once the constant expression interpreter is able to handle the checked arithmetic
+  // builtins in C. Currently, they're only a valid constant expression in C++ due to
+  // looking for an ICE in C. Also all values in the tests of n2683_2.c should be checked.
+}
+
+void test_invalid_input() {
+  _BitInt(33) a33 = 1;
+  char char_var = 'd'; // The ascii value of `d` is 100
+  bool bool_var = 1;
+  const int const_result = 0;
+  enum week{Mon, Tue, Wed};
+  enum week day = Mon;
+  int a = 100;
+  int b = 55;
+  int result = 10;
+  char plain_char[] = {U'牛'}; /* expected-warning {{implicit conversion from 'unsigned int' to 'char' changes value from 29275 to 91}}  */
+
+  // invalid operand argument
+  bool flag_no_bitint = ckd_add(&result, a33, a); /* expected-error {{operand argument to checked integer operation must be an integer type other than plain 'char', 'bool', bit-precise, or an enumeration ('_BitInt(33)' invalid)}} */
+  bool flag_no_bool = ckd_sub(&result, bool_var, b); /* expected-error {{operand argument to checked integer operation must be an integer type other than plain 'char', 'bool', bit-precise, or an enumeration ('bool' invalid)}} */
+  bool flag_no_char = ckd_mul(&result, char_var, a); /* expected-error {{operand argument to checked integer operation must be an integer type other than plain 'char', 'bool', bit-precise, or an enumeration ('char' invalid)}} */
+  bool flag_no_enum = ckd_mul(&result, day, b); /* expected-error {{operand argument to checked integer operation must be an integer type other than plain 'char', 'bool', bit-precise, or an enumeration ('enum week' invalid)}} */
+
+  // invalid result type
+  bool flag_nostr = ckd_sub(&plain_char, a, b); /* expected-error {{result argument to checked integer operation must be a pointer to a non-const integer type other than plain 'char', 'bool', bit-precise, or an enumeration ('char (*)[1]' invalid)}} */
+  bool flag_nobool = ckd_mul(&bool_var, a, b); /* expected-error {{result argument to checked integer operation must be a pointer to a non-const integer type other than plain 'char', 'bool', bit-precise, or an enumeration ('bool *' invalid)}} */
+  bool flag_noptr = ckd_add(result, a, b); /* expected-error {{result argument to checked integer operation must be a pointer to a non-const integer type other than plain 'char', 'bool', bit-precise, or an enumeration ('int' invalid)}} */
+  bool flag_noconst = ckd_sub(&const_result, a, b); /* expected-error {{result argument to checked integer operation must be a pointer to a non-const integer type other than plain 'char', 'bool', bit-precise, or an enumeration ('const int *' invalid)}} */
+}

diff  --git a/clang/test/C/C2x/n2683_2.c b/clang/test/C/C2x/n2683_2.c
new file mode 100644
index 000000000000000..247f6de8fe4bfe1
--- /dev/null
+++ b/clang/test/C/C2x/n2683_2.c
@@ -0,0 +1,66 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 3
+// RUN: %clang_cc1 -triple=x86_64 -emit-llvm -o - -std=c23 %s | FileCheck %s
+
+#include <stdckdint.h>
+#include <stdint.h>
+
+// CHECK-LABEL: define dso_local void @test_add_overflow_to64(
+// CHECK-SAME: ) #[[ATTR0:[0-9]+]] {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[RESULT64:%.*]] = alloca i64, align 8
+// CHECK-NEXT:    [[FLAG_ADD:%.*]] = alloca i8, align 1
+// CHECK-NEXT:    store i64 0, ptr [[RESULT64]], align 8
+// CHECK-NEXT:    [[TMP0:%.*]] = call { i64, i1 } @llvm.sadd.with.overflow.i64(i64 2147483647, i64 1)
+// CHECK-NEXT:    [[TMP1:%.*]] = extractvalue { i64, i1 } [[TMP0]], 1
+// CHECK-NEXT:    [[TMP2:%.*]] = extractvalue { i64, i1 } [[TMP0]], 0
+// CHECK-NEXT:    store i64 [[TMP2]], ptr [[RESULT64]], align 8
+// CHECK-NEXT:    [[FROMBOOL:%.*]] = zext i1 [[TMP1]] to i8
+// CHECK-NEXT:    store i8 [[FROMBOOL]], ptr [[FLAG_ADD]], align 1
+// CHECK-NEXT:    ret void
+//
+void test_add_overflow_to64() {
+  int64_t result64 = 0;
+  bool flag_add = ckd_add(&result64, INT32_MAX, 1);
+}
+
+// CHECK-LABEL: define dso_local void @test_sub_overflow(
+// CHECK-SAME: ) #[[ATTR0]] {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[RESULT32:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[FLAG_SUB:%.*]] = alloca i8, align 1
+// CHECK-NEXT:    store i32 0, ptr [[RESULT32]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 2147483647, i32 -1)
+// CHECK-NEXT:    [[TMP1:%.*]] = extractvalue { i32, i1 } [[TMP0]], 1
+// CHECK-NEXT:    [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP0]], 0
+// CHECK-NEXT:    store i32 [[TMP2]], ptr [[RESULT32]], align 4
+// CHECK-NEXT:    [[FROMBOOL:%.*]] = zext i1 [[TMP1]] to i8
+// CHECK-NEXT:    store i8 [[FROMBOOL]], ptr [[FLAG_SUB]], align 1
+// CHECK-NEXT:    ret void
+//
+void test_sub_overflow() {
+  int32_t result32 = 0;
+  bool flag_sub = ckd_sub(&result32, INT32_MAX, -1);
+}
+
+// CHECK-LABEL: define dso_local void @test_mul_normal(
+// CHECK-SAME: ) #[[ATTR0]] {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[RESULT:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[FLAG_MUL:%.*]] = alloca i8, align 1
+// CHECK-NEXT:    store i32 3, ptr [[A]], align 4
+// CHECK-NEXT:    store i32 0, ptr [[RESULT]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 [[TMP0]], i32 2)
+// CHECK-NEXT:    [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1
+// CHECK-NEXT:    [[TMP3:%.*]] = extractvalue { i32, i1 } [[TMP1]], 0
+// CHECK-NEXT:    store i32 [[TMP3]], ptr [[RESULT]], align 4
+// CHECK-NEXT:    [[FROMBOOL:%.*]] = zext i1 [[TMP2]] to i8
+// CHECK-NEXT:    store i8 [[FROMBOOL]], ptr [[FLAG_MUL]], align 1
+// CHECK-NEXT:    ret void
+//
+void test_mul_normal() {
+  int a = 3;
+  int result = 0;
+  bool flag_mul = ckd_mul(&result, a, 2);
+}

diff  --git a/clang/test/Headers/stdckdint.c b/clang/test/Headers/stdckdint.c
new file mode 100644
index 000000000000000..896c740360065b6
--- /dev/null
+++ b/clang/test/Headers/stdckdint.c
@@ -0,0 +1,53 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 3
+// RUN: %clang_cc1 -triple=x86_64 -emit-llvm -verify -std=c23 %s -o - | FileCheck %s
+
+// expected-no-diagnostics
+
+#include <stdckdint.h>
+
+_Static_assert(__STDC_VERSION_STDCKDINT_H__ == 202311L, "");
+
+// CHECK-LABEL: define dso_local zeroext i1 @test_ckd_add(
+// CHECK-SAME: ) #[[ATTR0:[0-9]+]] {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[RESULT:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 -1073741826, i32 -1073741826)
+// CHECK-NEXT:    [[TMP1:%.*]] = extractvalue { i32, i1 } [[TMP0]], 1
+// CHECK-NEXT:    [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP0]], 0
+// CHECK-NEXT:    store i32 [[TMP2]], ptr [[RESULT]], align 4
+// CHECK-NEXT:    ret i1 [[TMP1]]
+//
+bool test_ckd_add() {
+  int result;
+  return ckd_add(&result, -1073741826, -1073741826);
+}
+
+// CHECK-LABEL: define dso_local zeroext i1 @test_ckd_sub(
+// CHECK-SAME: ) #[[ATTR0]] {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[RESULT:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 -1073741826, i32 1073741826)
+// CHECK-NEXT:    [[TMP1:%.*]] = extractvalue { i32, i1 } [[TMP0]], 1
+// CHECK-NEXT:    [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP0]], 0
+// CHECK-NEXT:    store i32 [[TMP2]], ptr [[RESULT]], align 4
+// CHECK-NEXT:    ret i1 [[TMP1]]
+//
+bool test_ckd_sub() {
+  int result;
+  return ckd_sub(&result, -1073741826, 1073741826);
+}
+
+// CHECK-LABEL: define dso_local zeroext i1 @test_ckd_mul(
+// CHECK-SAME: ) #[[ATTR0]] {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[RESULT:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 -1073741826, i32 2)
+// CHECK-NEXT:    [[TMP1:%.*]] = extractvalue { i32, i1 } [[TMP0]], 1
+// CHECK-NEXT:    [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP0]], 0
+// CHECK-NEXT:    store i32 [[TMP2]], ptr [[RESULT]], align 4
+// CHECK-NEXT:    ret i1 [[TMP1]]
+//
+bool test_ckd_mul() {
+  int result;
+  return ckd_mul(&result, -1073741826, 2);
+}

diff  --git a/clang/test/Sema/builtins-overflow.c b/clang/test/Sema/builtins-overflow.c
index f41fddd2cafb459..302489c19e37964 100644
--- a/clang/test/Sema/builtins-overflow.c
+++ b/clang/test/Sema/builtins-overflow.c
@@ -14,11 +14,11 @@ void test(void) {
   __builtin_add_overflow();  // expected-error {{too few arguments to function call, expected 3, have 0}}
   __builtin_add_overflow(1, 1, 1, 1);  // expected-error {{too many arguments to function call, expected 3, have 4}}
 
-  __builtin_add_overflow(c, 1, &r);  // expected-error {{operand argument to overflow builtin must be an integer ('const char *' invalid)}}
-  __builtin_add_overflow(1, c, &r);  // expected-error {{operand argument to overflow builtin must be an integer ('const char *' invalid)}}
-  __builtin_add_overflow(1, 1, 3);  // expected-error {{result argument to overflow builtin must be a pointer to a non-const integer ('int' invalid)}}
-  __builtin_add_overflow(1, 1, &f);  // expected-error {{result argument to overflow builtin must be a pointer to a non-const integer ('float *' invalid)}}
-  __builtin_add_overflow(1, 1, &q);  // expected-error {{result argument to overflow builtin must be a pointer to a non-const integer ('const unsigned int *' invalid)}}
+  __builtin_add_overflow(c, 1, &r);  // expected-error {{operand argument to overflow builtin must be an integer type ('const char *' invalid)}}
+  __builtin_add_overflow(1, c, &r);  // expected-error {{operand argument to overflow builtin must be an integer type ('const char *' invalid)}}
+  __builtin_add_overflow(1, 1, 3);  // expected-error {{result argument to overflow builtin must be a pointer to a non-const integer type ('int' invalid)}}
+  __builtin_add_overflow(1, 1, &f);  // expected-error {{result argument to overflow builtin must be a pointer to a non-const integer type ('float *' invalid)}}
+  __builtin_add_overflow(1, 1, &q);  // expected-error {{result argument to overflow builtin must be a pointer to a non-const integer type ('const unsigned int *' invalid)}}
 
   {
     _BitInt(128) x = 1;

diff  --git a/clang/www/c_status.html b/clang/www/c_status.html
index 13bb1971c61deb7..0e0ea0b179e4c87 100644
--- a/clang/www/c_status.html
+++ b/clang/www/c_status.html
@@ -887,6 +887,11 @@ <h2 id="c2x">C23 implementation status</h2>
       <td><a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2672.pdf">N2672</a></td>
       <td class="full" align="center">Yes</td>
     </tr>
+    <tr>
+      <td>Towards Integer Safety</td>
+      <td><a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2683.pdf">N2683</a></td>
+      <td class="full" align="center">Clang 18</td>
+    </tr>
     <tr id="_BitInt">
       <td rowspan="5">Adding Fundamental Type for N-bit Integers</td>
     </tr>


        


More information about the cfe-commits mailing list