Skip to content

Commit 3694697

Browse files
committed
[clang] Implement C23 <stdckdint.h>
#62248 Reviewed By: yabinc, aaron.ballman, #clang-language-wg Differential Revision: https://reviews.llvm.org/D157331
1 parent 81d0470 commit 3694697

File tree

12 files changed

+273
-14
lines changed

12 files changed

+273
-14
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,9 @@ C23 Feature Support
176176
- Clang now supports `requires c23` for module maps.
177177
- Clang now supports ``N3007 Type inference for object definitions``.
178178

179+
- Clang now supports ``<stdckdint.h>`` which defines several macros for performing
180+
checked integer arithmetic.
181+
179182
Non-comprehensive list of changes in this release
180183
-------------------------------------------------
181184

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8690,10 +8690,13 @@ def warn_atomic_implicit_seq_cst : Warning<
86908690
InGroup<DiagGroup<"atomic-implicit-seq-cst">>, DefaultIgnore;
86918691

86928692
def err_overflow_builtin_must_be_int : Error<
8693-
"operand argument to overflow builtin must be an integer (%0 invalid)">;
8693+
"operand argument to %select{overflow builtin|checked integer operation}0 "
8694+
"must be an integer type %select{|other than plain 'char', 'bool', bit-precise, "
8695+
"or an enumeration }0(%1 invalid)">;
86948696
def err_overflow_builtin_must_be_ptr_int : Error<
8695-
"result argument to overflow builtin must be a pointer "
8696-
"to a non-const integer (%0 invalid)">;
8697+
"result argument to %select{overflow builtin|checked integer operation}0 "
8698+
"must be a pointer to a non-const integer type %select{|other than plain 'char', "
8699+
"'bool', bit-precise, or an enumeration }0(%1 invalid)">;
86978700
def err_overflow_builtin_bit_int_max_size : Error<
86988701
"__builtin_mul_overflow does not support 'signed _BitInt' operands of more "
86998702
"than %0 bits">;

clang/lib/Headers/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ set(core_files
1717
__stdarg_va_list.h
1818
stdatomic.h
1919
stdbool.h
20+
stdckdint.h
2021
stddef.h
2122
__stddef_max_align_t.h
2223
__stddef_null.h

clang/lib/Headers/stdckdint.h

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*===---- stdckdint.h - Standard header for checking integer----------------===
2+
*
3+
* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
* See https://llvm.org/LICENSE.txt for license information.
5+
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
*
7+
*===-----------------------------------------------------------------------===
8+
*/
9+
10+
#ifndef __STDCKDINT_H
11+
#define __STDCKDINT_H
12+
13+
/* If we're hosted, fall back to the system's stdckdint.h. FreeBSD, for
14+
* example, already has a Clang-compatible stdckdint.h header.
15+
*
16+
* The `stdckdint.h` header requires C 23 or newer.
17+
*/
18+
#if __STDC_HOSTED__ && __has_include_next(<stdckdint.h>)
19+
#include_next <stdckdint.h>
20+
#else
21+
22+
/* C23 7.20.1 Defines several macros for performing checked integer arithmetic*/
23+
24+
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L
25+
#define __STDC_VERSION_STDCKDINT_H__ 202311L
26+
27+
// Both A and B shall be any integer type other than "plain" char, bool, a bit-
28+
// precise integer type, or an enumerated type, and they need not be the same.
29+
30+
// R shall be a modifiable lvalue of any integer type other than "plain" char,
31+
// bool, a bit-precise integer type, or an enumerated type. It shouldn't be
32+
// short type, either. Otherwise, it may be unable to hold two the result of
33+
// operating two 'int's.
34+
35+
// A diagnostic message will be produced if A or B are not suitable integer
36+
// types, or if R is not a modifiable lvalue of a suitable integer type or R
37+
// is short type.
38+
#define ckd_add(R, A, B) __builtin_add_overflow((A), (B), (R))
39+
#define ckd_sub(R, A, B) __builtin_sub_overflow((A), (B), (R))
40+
#define ckd_mul(R, A, B) __builtin_mul_overflow((A), (B), (R))
41+
#endif
42+
43+
#endif /* __STDC_HOSTED__ */
44+
#endif /* __STDCKDINT_H */

clang/lib/Lex/PPDirectives.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -231,9 +231,10 @@ static bool warnByDefaultOnWrongCase(StringRef Include) {
231231
.Cases("assert.h", "complex.h", "ctype.h", "errno.h", "fenv.h", true)
232232
.Cases("float.h", "inttypes.h", "iso646.h", "limits.h", "locale.h", true)
233233
.Cases("math.h", "setjmp.h", "signal.h", "stdalign.h", "stdarg.h", true)
234-
.Cases("stdatomic.h", "stdbool.h", "stddef.h", "stdint.h", "stdio.h", true)
235-
.Cases("stdlib.h", "stdnoreturn.h", "string.h", "tgmath.h", "threads.h", true)
236-
.Cases("time.h", "uchar.h", "wchar.h", "wctype.h", true)
234+
.Cases("stdatomic.h", "stdbool.h", "stdckdint.h", "stddef.h", true)
235+
.Cases("stdint.h", "stdio.h", "stdlib.h", "stdnoreturn.h", true)
236+
.Cases("string.h", "tgmath.h", "threads.h", "time.h", "uchar.h", true)
237+
.Cases("wchar.h", "wctype.h", true)
237238

238239
// C++ headers for C library facilities
239240
.Cases("cassert", "ccomplex", "cctype", "cerrno", "cfenv", true)

clang/lib/Sema/SemaChecking.cpp

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -370,16 +370,43 @@ static bool SemaBuiltinOverflow(Sema &S, CallExpr *TheCall,
370370
if (checkArgCount(S, TheCall, 3))
371371
return true;
372372

373+
std::pair<unsigned, const char *> Builtins[] = {
374+
{ Builtin::BI__builtin_add_overflow, "ckd_add" },
375+
{ Builtin::BI__builtin_sub_overflow, "ckd_sub" },
376+
{ Builtin::BI__builtin_mul_overflow, "ckd_mul" },
377+
};
378+
379+
bool CkdOperation = llvm::any_of(Builtins, [&](const std::pair<unsigned,
380+
const char *> &P) {
381+
return BuiltinID == P.first && TheCall->getExprLoc().isMacroID() &&
382+
Lexer::getImmediateMacroName(TheCall->getExprLoc(),
383+
S.getSourceManager(), S.getLangOpts()) == P.second;
384+
});
385+
386+
auto ValidCkdIntType = [](QualType QT) {
387+
// A valid checked integer type is an integer type other than a plain char,
388+
// bool, a bit-precise type, or an enumeration type.
389+
if (const auto *BT = QT.getCanonicalType()->getAs<BuiltinType>())
390+
return (BT->getKind() >= BuiltinType::Short &&
391+
BT->getKind() <= BuiltinType::Int128) || (
392+
BT->getKind() >= BuiltinType::UShort &&
393+
BT->getKind() <= BuiltinType::UInt128) ||
394+
BT->getKind() == BuiltinType::UChar ||
395+
BT->getKind() == BuiltinType::SChar;
396+
return false;
397+
};
398+
373399
// First two arguments should be integers.
374400
for (unsigned I = 0; I < 2; ++I) {
375401
ExprResult Arg = S.DefaultFunctionArrayLvalueConversion(TheCall->getArg(I));
376402
if (Arg.isInvalid()) return true;
377403
TheCall->setArg(I, Arg.get());
378404

379405
QualType Ty = Arg.get()->getType();
380-
if (!Ty->isIntegerType()) {
406+
bool IsValid = CkdOperation ? ValidCkdIntType(Ty) : Ty->isIntegerType();
407+
if (!IsValid) {
381408
S.Diag(Arg.get()->getBeginLoc(), diag::err_overflow_builtin_must_be_int)
382-
<< Ty << Arg.get()->getSourceRange();
409+
<< CkdOperation << Ty << Arg.get()->getSourceRange();
383410
return true;
384411
}
385412
}
@@ -396,10 +423,11 @@ static bool SemaBuiltinOverflow(Sema &S, CallExpr *TheCall,
396423
const auto *PtrTy = Ty->getAs<PointerType>();
397424
if (!PtrTy ||
398425
!PtrTy->getPointeeType()->isIntegerType() ||
426+
(!ValidCkdIntType(PtrTy->getPointeeType()) && CkdOperation) ||
399427
PtrTy->getPointeeType().isConstQualified()) {
400428
S.Diag(Arg.get()->getBeginLoc(),
401429
diag::err_overflow_builtin_must_be_ptr_int)
402-
<< Ty << Arg.get()->getSourceRange();
430+
<< CkdOperation << Ty << Arg.get()->getSourceRange();
403431
return true;
404432
}
405433
}

clang/test/C/C2x/n2359.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,7 @@
3434
// expected-error@-1 {{"__STDC_VERSION_STDINT_H__ not defined"}}
3535
#endif
3636

37+
#include <stdckdint.h>
38+
#ifndef __STDC_VERSION_STDCKDINT_H__
39+
#error "__STDC_VERSION_STDCKDINT_H__ not defined"
40+
#endif

clang/test/C/C2x/n2683.c

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 3
2+
// RUN: %clang_cc1 -triple=x86_64 -verify -ffreestanding -std=c23 %s
3+
4+
/* WG14 N2683: Clang 18
5+
* Towards Integer Safety
6+
*/
7+
#include <stdckdint.h>
8+
#include <stddef.h>
9+
#include <stdint.h>
10+
11+
void test_semantic() {
12+
int64_t result64 = 0;
13+
int32_t result32 = 0;
14+
wchar_t wide_char = L'A'; // The ascii value of `A` is 65
15+
16+
bool flag_add = ckd_add(&result64, INT32_MAX, 1);
17+
bool flag_sub = ckd_sub(&result32, INT32_MAX, -1);
18+
bool flag_mul = ckd_mul(&result64, INT64_MAX, 1);
19+
20+
bool flag = ckd_add(&result64, wide_char, result32); // In C, wchar_t is a typedef to some integer type and is allowed.
21+
22+
// FIXME: add static_assert calls to check the resulting values for correctness
23+
// once the constant expression interpreter is able to handle the checked arithmetic
24+
// builtins in C. Currently, they're only a valid constant expression in C++ due to
25+
// looking for an ICE in C. Also all values in the tests of n2683_2.c should be checked.
26+
}
27+
28+
void test_invalid_input() {
29+
_BitInt(33) a33 = 1;
30+
char char_var = 'd'; // The ascii value of `d` is 100
31+
bool bool_var = 1;
32+
const int const_result = 0;
33+
enum week{Mon, Tue, Wed};
34+
enum week day = Mon;
35+
int a = 100;
36+
int b = 55;
37+
int result = 10;
38+
char plain_char[] = {U'牛'}; /* expected-warning {{implicit conversion from 'unsigned int' to 'char' changes value from 29275 to 91}} */
39+
40+
// invalid operand argument
41+
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)}} */
42+
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)}} */
43+
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)}} */
44+
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)}} */
45+
46+
// invalid result type
47+
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)}} */
48+
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)}} */
49+
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)}} */
50+
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)}} */
51+
}

clang/test/C/C2x/n2683_2.c

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 3
2+
// RUN: %clang_cc1 -triple=x86_64 -emit-llvm -o - -std=c23 %s | FileCheck %s
3+
4+
#include <stdckdint.h>
5+
#include <stdint.h>
6+
7+
// CHECK-LABEL: define dso_local void @test_add_overflow_to64(
8+
// CHECK-SAME: ) #[[ATTR0:[0-9]+]] {
9+
// CHECK-NEXT: entry:
10+
// CHECK-NEXT: [[RESULT64:%.*]] = alloca i64, align 8
11+
// CHECK-NEXT: [[FLAG_ADD:%.*]] = alloca i8, align 1
12+
// CHECK-NEXT: store i64 0, ptr [[RESULT64]], align 8
13+
// CHECK-NEXT: [[TMP0:%.*]] = call { i64, i1 } @llvm.sadd.with.overflow.i64(i64 2147483647, i64 1)
14+
// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { i64, i1 } [[TMP0]], 1
15+
// CHECK-NEXT: [[TMP2:%.*]] = extractvalue { i64, i1 } [[TMP0]], 0
16+
// CHECK-NEXT: store i64 [[TMP2]], ptr [[RESULT64]], align 8
17+
// CHECK-NEXT: [[FROMBOOL:%.*]] = zext i1 [[TMP1]] to i8
18+
// CHECK-NEXT: store i8 [[FROMBOOL]], ptr [[FLAG_ADD]], align 1
19+
// CHECK-NEXT: ret void
20+
//
21+
void test_add_overflow_to64() {
22+
int64_t result64 = 0;
23+
bool flag_add = ckd_add(&result64, INT32_MAX, 1);
24+
}
25+
26+
// CHECK-LABEL: define dso_local void @test_sub_overflow(
27+
// CHECK-SAME: ) #[[ATTR0]] {
28+
// CHECK-NEXT: entry:
29+
// CHECK-NEXT: [[RESULT32:%.*]] = alloca i32, align 4
30+
// CHECK-NEXT: [[FLAG_SUB:%.*]] = alloca i8, align 1
31+
// CHECK-NEXT: store i32 0, ptr [[RESULT32]], align 4
32+
// CHECK-NEXT: [[TMP0:%.*]] = call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 2147483647, i32 -1)
33+
// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { i32, i1 } [[TMP0]], 1
34+
// CHECK-NEXT: [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP0]], 0
35+
// CHECK-NEXT: store i32 [[TMP2]], ptr [[RESULT32]], align 4
36+
// CHECK-NEXT: [[FROMBOOL:%.*]] = zext i1 [[TMP1]] to i8
37+
// CHECK-NEXT: store i8 [[FROMBOOL]], ptr [[FLAG_SUB]], align 1
38+
// CHECK-NEXT: ret void
39+
//
40+
void test_sub_overflow() {
41+
int32_t result32 = 0;
42+
bool flag_sub = ckd_sub(&result32, INT32_MAX, -1);
43+
}
44+
45+
// CHECK-LABEL: define dso_local void @test_mul_normal(
46+
// CHECK-SAME: ) #[[ATTR0]] {
47+
// CHECK-NEXT: entry:
48+
// CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
49+
// CHECK-NEXT: [[RESULT:%.*]] = alloca i32, align 4
50+
// CHECK-NEXT: [[FLAG_MUL:%.*]] = alloca i8, align 1
51+
// CHECK-NEXT: store i32 3, ptr [[A]], align 4
52+
// CHECK-NEXT: store i32 0, ptr [[RESULT]], align 4
53+
// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A]], align 4
54+
// CHECK-NEXT: [[TMP1:%.*]] = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 [[TMP0]], i32 2)
55+
// CHECK-NEXT: [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1
56+
// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i32, i1 } [[TMP1]], 0
57+
// CHECK-NEXT: store i32 [[TMP3]], ptr [[RESULT]], align 4
58+
// CHECK-NEXT: [[FROMBOOL:%.*]] = zext i1 [[TMP2]] to i8
59+
// CHECK-NEXT: store i8 [[FROMBOOL]], ptr [[FLAG_MUL]], align 1
60+
// CHECK-NEXT: ret void
61+
//
62+
void test_mul_normal() {
63+
int a = 3;
64+
int result = 0;
65+
bool flag_mul = ckd_mul(&result, a, 2);
66+
}

clang/test/Headers/stdckdint.c

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 3
2+
// RUN: %clang_cc1 -triple=x86_64 -emit-llvm -verify -std=c23 %s -o - | FileCheck %s
3+
4+
// expected-no-diagnostics
5+
6+
#include <stdckdint.h>
7+
8+
_Static_assert(__STDC_VERSION_STDCKDINT_H__ == 202311L, "");
9+
10+
// CHECK-LABEL: define dso_local zeroext i1 @test_ckd_add(
11+
// CHECK-SAME: ) #[[ATTR0:[0-9]+]] {
12+
// CHECK-NEXT: entry:
13+
// CHECK-NEXT: [[RESULT:%.*]] = alloca i32, align 4
14+
// CHECK-NEXT: [[TMP0:%.*]] = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 -1073741826, i32 -1073741826)
15+
// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { i32, i1 } [[TMP0]], 1
16+
// CHECK-NEXT: [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP0]], 0
17+
// CHECK-NEXT: store i32 [[TMP2]], ptr [[RESULT]], align 4
18+
// CHECK-NEXT: ret i1 [[TMP1]]
19+
//
20+
bool test_ckd_add() {
21+
int result;
22+
return ckd_add(&result, -1073741826, -1073741826);
23+
}
24+
25+
// CHECK-LABEL: define dso_local zeroext i1 @test_ckd_sub(
26+
// CHECK-SAME: ) #[[ATTR0]] {
27+
// CHECK-NEXT: entry:
28+
// CHECK-NEXT: [[RESULT:%.*]] = alloca i32, align 4
29+
// CHECK-NEXT: [[TMP0:%.*]] = call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 -1073741826, i32 1073741826)
30+
// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { i32, i1 } [[TMP0]], 1
31+
// CHECK-NEXT: [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP0]], 0
32+
// CHECK-NEXT: store i32 [[TMP2]], ptr [[RESULT]], align 4
33+
// CHECK-NEXT: ret i1 [[TMP1]]
34+
//
35+
bool test_ckd_sub() {
36+
int result;
37+
return ckd_sub(&result, -1073741826, 1073741826);
38+
}
39+
40+
// CHECK-LABEL: define dso_local zeroext i1 @test_ckd_mul(
41+
// CHECK-SAME: ) #[[ATTR0]] {
42+
// CHECK-NEXT: entry:
43+
// CHECK-NEXT: [[RESULT:%.*]] = alloca i32, align 4
44+
// CHECK-NEXT: [[TMP0:%.*]] = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 -1073741826, i32 2)
45+
// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { i32, i1 } [[TMP0]], 1
46+
// CHECK-NEXT: [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP0]], 0
47+
// CHECK-NEXT: store i32 [[TMP2]], ptr [[RESULT]], align 4
48+
// CHECK-NEXT: ret i1 [[TMP1]]
49+
//
50+
bool test_ckd_mul() {
51+
int result;
52+
return ckd_mul(&result, -1073741826, 2);
53+
}

clang/test/Sema/builtins-overflow.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ void test(void) {
1414
__builtin_add_overflow(); // expected-error {{too few arguments to function call, expected 3, have 0}}
1515
__builtin_add_overflow(1, 1, 1, 1); // expected-error {{too many arguments to function call, expected 3, have 4}}
1616

17-
__builtin_add_overflow(c, 1, &r); // expected-error {{operand argument to overflow builtin must be an integer ('const char *' invalid)}}
18-
__builtin_add_overflow(1, c, &r); // expected-error {{operand argument to overflow builtin must be an integer ('const char *' invalid)}}
19-
__builtin_add_overflow(1, 1, 3); // expected-error {{result argument to overflow builtin must be a pointer to a non-const integer ('int' invalid)}}
20-
__builtin_add_overflow(1, 1, &f); // expected-error {{result argument to overflow builtin must be a pointer to a non-const integer ('float *' invalid)}}
21-
__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)}}
17+
__builtin_add_overflow(c, 1, &r); // expected-error {{operand argument to overflow builtin must be an integer type ('const char *' invalid)}}
18+
__builtin_add_overflow(1, c, &r); // expected-error {{operand argument to overflow builtin must be an integer type ('const char *' invalid)}}
19+
__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)}}
20+
__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)}}
21+
__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)}}
2222

2323
{
2424
_BitInt(128) x = 1;

clang/www/c_status.html

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -887,6 +887,11 @@ <h2 id="c2x">C23 implementation status</h2>
887887
<td><a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2672.pdf">N2672</a></td>
888888
<td class="full" align="center">Yes</td>
889889
</tr>
890+
<tr>
891+
<td>Towards Integer Safety</td>
892+
<td><a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2683.pdf">N2683</a></td>
893+
<td class="full" align="center">Clang 18</td>
894+
</tr>
890895
<tr id="_BitInt">
891896
<td rowspan="5">Adding Fundamental Type for N-bit Integers</td>
892897
</tr>

0 commit comments

Comments
 (0)