ZijunZhao updated this revision to Diff 550910.
ZijunZhao added a comment.

1. separate two files in clang/test/C/C2x
2. make some update about the macro __STDC_VERSION_STDCKDINT_H__ add the test 
for testing it


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D157331/new/

https://reviews.llvm.org/D157331

Files:
  clang/docs/ReleaseNotes.rst
  clang/lib/Headers/CMakeLists.txt
  clang/lib/Headers/stdckdint.h
  clang/lib/Lex/ModuleMap.cpp
  clang/lib/Lex/PPDirectives.cpp
  clang/test/C/C2x/n2359.c
  clang/test/C/C2x/n2683.c
  clang/test/C/C2x/n2683_2.c
  clang/test/Headers/stdckdint.c
  clang/test/Modules/Inputs/System/usr/include/module.map
  clang/www/c_status.html

Index: clang/www/c_status.html
===================================================================
--- clang/www/c_status.html
+++ clang/www/c_status.html
@@ -886,6 +886,11 @@
       <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>
Index: clang/test/Modules/Inputs/System/usr/include/module.map
===================================================================
--- clang/test/Modules/Inputs/System/usr/include/module.map
+++ clang/test/Modules/Inputs/System/usr/include/module.map
@@ -14,6 +14,11 @@
     header "stdbool.h"
   }
 
+  // In both directories (compiler support version wins, does not forward)
+  module stdckdint {
+    header "stdckdint.h"
+  }
+
   // In both directories (compiler support version wins, forwards)
   module stdint {
     header "stdint.h"
Index: clang/test/Headers/stdckdint.c
===================================================================
--- /dev/null
+++ clang/test/Headers/stdckdint.c
@@ -0,0 +1,49 @@
+// RUN: %clang_cc1 -emit-llvm -verify -fgnuc-version=4.2.1 -std=c23 %s -o - | FileCheck %s
+// expected-no-diagnostics
+#include <stdckdint.h>
+
+// CHECK-LABEL: define dso_local zeroext i1 @test_ckd_add() #0 {
+// CHECK:  entry:
+// CHECK:    %result = alloca i32, align 4
+// CHECK:    %0 = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 -1073741826, i32 -1073741826)
+// CHECK:    %1 = extractvalue { i32, i1 } %0, 1
+// CHECK:    %2 = extractvalue { i32, i1 } %0, 0
+// CHECK:    store i32 %2, ptr %result, align 4
+// CHECK:    ret i1 %1
+// CHECK:    }
+// CHECK:    ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
+// CHECK:    declare { i32, i1 } @llvm.sadd.with.overflow.i32(i32, i32) #1
+bool test_ckd_add() {
+  int result;
+  return ckd_add(&result, -1073741826, -1073741826);
+}
+
+// CHECK-LABEL: define dso_local zeroext i1 @test_ckd_sub() #0 {
+// CHECK:  entry:
+// CHECK:    %result = alloca i32, align 4
+// CHECK:    %0 = call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 -1073741826, i32 1073741826)
+// CHECK:    %1 = extractvalue { i32, i1 } %0, 1
+// CHECK:    %2 = extractvalue { i32, i1 } %0, 0
+// CHECK:    store i32 %2, ptr %result, align 4
+// CHECK:    ret i1 %1
+// CHECK:    }
+// CHECK:    declare { i32, i1 } @llvm.ssub.with.overflow.i32(i32, i32) #1
+bool test_ckd_sub() {
+  int result;
+  return ckd_sub(&result, -1073741826, 1073741826);
+}
+
+// CHECK-LABEL: define dso_local zeroext i1 @test_ckd_mul() #0 {
+// CHECK:  entry:
+// CHECK:    %result = alloca i32, align 4
+// CHECK:    %0 = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 -1073741826, i32 2)
+// CHECK:    %1 = extractvalue { i32, i1 } %0, 1
+// CHECK:    %2 = extractvalue { i32, i1 } %0, 0
+// CHECK:    store i32 %2, ptr %result, align 4
+// CHECK:    ret i1 %1
+// CHECK:    }
+// CHECK:    declare { i32, i1 } @llvm.smul.with.overflow.i32(i32, i32) #1
+bool test_ckd_mul() {
+  int result;
+  return ckd_mul(&result, -1073741826, 2);
+}
Index: clang/test/C/C2x/n2683_2.c
===================================================================
--- /dev/null
+++ clang/test/C/C2x/n2683_2.c
@@ -0,0 +1,62 @@
+// RUN: %clang_cc1 -emit-llvm -o - -std=c23 %s | FileCheck %s
+// expected-no-diagnostics
+
+#include <stdckdint.h>
+#include <stdint.h>
+// CHECK-LABEL: define dso_local void @test_add_overflow_to64() #0 {
+// CHECK:  entry:
+// CHECK:    %result64 = alloca i64, align 8
+// CHECK:    %flag_add = alloca i8, align 1
+// CHECK:    store i64 0, ptr %result64, align 8
+// CHECK:    %0 = call { i64, i1 } @llvm.sadd.with.overflow.i64(i64 2147483647, i64 1)
+// CHECK:    %1 = extractvalue { i64, i1 } %0, 1 
+// CHECK:    %2 = extractvalue { i64, i1 } %0, 0
+// CHECK:    store i64 %2, ptr %result64, align 8
+// CHECK:    %frombool = zext i1 %1 to i8
+// CHECK:    store i8 %frombool, ptr %flag_add, align 1
+// CHECK:    ret void
+// CHECK:  }
+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() #0 {
+// CHECK:  entry:
+// CHECK:    %result32 = alloca i32, align 4
+// CHECK:    %flag_sub = alloca i8, align 1
+// CHECK:    store i32 0, ptr %result32, align 4
+// CHECK:    %0 = call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 2147483647, i32 -1)
+// CHECK:    %1 = extractvalue { i32, i1 } %0, 1 
+// CHECK:    %2 = extractvalue { i32, i1 } %0, 0
+// CHECK:    store i32 %2, ptr %result32, align 4
+// CHECK:    %frombool = zext i1 %1 to i8 
+// CHECK:    store i8 %frombool, ptr %flag_sub, align 1 
+// CHECK:    ret void
+// CHECK:  }
+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() #0 {
+// CHECK:  entry:
+// CHECK:    %a = alloca i32, align 4
+// CHECK:    %result = alloca i32, align 4
+// CHECK:    %flag_mul = alloca i8, align 1
+// CHECK:    store i32 3, ptr %a, align 4
+// CHECK:    store i32 0, ptr %result, align 4
+// CHECK:    %0 = load i32, ptr %a, align 4
+// CHECK:    %1 = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 %0, i32 2)
+// CHECK:    %2 = extractvalue { i32, i1 } %1, 1 
+// CHECK:    %3 = extractvalue { i32, i1 } %1, 0
+// CHECK:    store i32 %3, ptr %result, align 4
+// CHECK:    %frombool = zext i1 %2 to i8 
+// CHECK:    store i8 %frombool, ptr %flag_mul, align 1 
+// CHECK:    ret void
+// CHECK:  }
+void test_mul_normal() {
+    int a = 3;
+    int result = 0;
+    bool flag_mul = ckd_mul(&result, a, 2);
+}
Index: clang/test/C/C2x/n2683.c
===================================================================
--- /dev/null
+++ clang/test/C/C2x/n2683.c
@@ -0,0 +1,30 @@
+// RUN: %clang_cc1 -verify -ffreestanding -std=c23 %s
+
+/* WG14 N2683: Clang 18
+ * Define several macros for performing checked integer arithmetic
+ */
+#include <stdckdint.h>
+
+void test_semantic() {
+    _BitInt(33) a33 = 1;
+    char char_var = 'd'; // The ascii value of `d` is 100
+    bool bool_var = 1;
+    enum week{Mon, Tue, Wed};
+    enum week day = Mon;
+    int result;
+
+    bool flag_add = ckd_add(&result, a33, char_var);
+    bool flag_sub = ckd_sub(&result, bool_var, day);
+    bool flag_mul = ckd_mul(&result, day, char_var);
+}
+
+void test_invalid_input() {
+    _BitInt(33) a33 = 1;
+    char char_var = 'd'; // The ascii value of `d` is 100
+    bool bool_var = 1;
+    enum week{Mon, Tue, Wed};
+    enum week day = Mon;
+    char plain_char[] = {U'牛'}; /* expected-warning {{implicit conversion from 'unsigned int' to 'char' changes value from 29275 to 91}}  */
+    bool flag_invalid = ckd_sub(&plain_char, char_var, day); /* expected-error {{result argument to overflow builtin must be a pointer to a non-const integer ('char (*)[1]' invalid)}} */
+    bool flag_noptr = ckd_add(day, a33, bool_var); /* expected-error {{result argument to overflow builtin must be a pointer to a non-const integer ('enum week' invalid)}} */
+}
Index: clang/test/C/C2x/n2359.c
===================================================================
--- clang/test/C/C2x/n2359.c
+++ clang/test/C/C2x/n2359.c
@@ -34,3 +34,8 @@
 // expected-error@-1 {{"__STDC_VERSION_STDINT_H__ not defined"}}
 #endif
 
+#include <stdckdint.h>
+#ifndef __STDC_VERSION_STDCKDINT_H__
+#error "__STDC_VERSION_STDCKDINT_H__ not defined"
+// expected-error@-1 {{"__STDC_VERSION_STDCKDINT_H__ not defined"}}
+#endif
Index: clang/lib/Lex/PPDirectives.cpp
===================================================================
--- clang/lib/Lex/PPDirectives.cpp
+++ clang/lib/Lex/PPDirectives.cpp
@@ -231,7 +231,8 @@
     .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("stdatomic.h", "stdbool.h", "stdckdint.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)
 
Index: clang/lib/Lex/ModuleMap.cpp
===================================================================
--- clang/lib/Lex/ModuleMap.cpp
+++ clang/lib/Lex/ModuleMap.cpp
@@ -385,6 +385,7 @@
            .Case("stdarg.h", true)
            .Case("stdatomic.h", true)
            .Case("stdbool.h", true)
+           .Case("stdckdint.h", true)
            .Case("stddef.h", true)
            .Case("stdint.h", true)
            .Case("tgmath.h", true)
Index: clang/lib/Headers/stdckdint.h
===================================================================
--- /dev/null
+++ clang/lib/Headers/stdckdint.h
@@ -0,0 +1,20 @@
+/*===---- 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
+
+/* C23 7.20.1 Defines several macros for performing checked integer arithmetic*/
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 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
+
+#endif /* __STDCKDINT_H */
Index: clang/lib/Headers/CMakeLists.txt
===================================================================
--- clang/lib/Headers/CMakeLists.txt
+++ clang/lib/Headers/CMakeLists.txt
@@ -12,6 +12,7 @@
   stdarg.h
   stdatomic.h
   stdbool.h
+  stdckdint.h
   stddef.h
   __stddef_max_align_t.h
   stdint.h
Index: clang/docs/ReleaseNotes.rst
===================================================================
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -103,6 +103,10 @@
   previous placeholder value. Clang continues to accept ``-std=c2x`` and
   ``-std=gnu2x`` as aliases for C23 and GNU C23, respectively.
 
+- Clang now adds <stdckdint.h> which defines several macros for performing
+  checked integer arithmetic. The macro ``__STDC_VERSION_STDCKDINT_H__``
+  is an integer constant expression with a value equivalent to ``202311L``.
+
 Non-comprehensive list of changes in this release
 -------------------------------------------------
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to