[clang] d083adb - Prohibit use of _ExtInt in atomic intrinsic
Erich Keane via cfe-commits
cfe-commits at lists.llvm.org
Tue Jul 14 06:11:19 PDT 2020
Author: Mott, Jeffrey T
Date: 2020-07-14T06:11:04-07:00
New Revision: d083adb068e781a2fc35aea8c6b7cccd566a735f
URL: https://github.com/llvm/llvm-project/commit/d083adb068e781a2fc35aea8c6b7cccd566a735f
DIFF: https://github.com/llvm/llvm-project/commit/d083adb068e781a2fc35aea8c6b7cccd566a735f.diff
LOG: Prohibit use of _ExtInt in atomic intrinsic
The _ExtInt type allows custom width integers, but the atomic memory
access's operand must have a power-of-two size. _ExtInts with
non-power-of-two size should not be allowed for atomic intrinsic.
Before this change:
$ cat test.c
typedef unsigned _ExtInt(42) dtype;
void verify_binary_op_nand(dtype* pval1, dtype val2)
{ __sync_nand_and_fetch(pval1, val2); }
$ clang test.c
clang-11:
/home/ubuntu/llvm_workspace/llvm/clang/lib/CodeGen/CGBuiltin.cpp:117:
llvm::Value*
EmitToInt(clang::CodeGen::CodeGenFunction&, llvm::Value*,
clang::QualType, llvm::IntegerType*): Assertion `V->getType() ==
IntType' failed.
PLEASE submit a bug report to https://bugs.llvm.org/ and include the
crash backtrace, preprocessed source, and associated run script.
After this change:
$ clang test.c
test.c:3:30: error: Atomic memory operand must have a power-of-two size
{ __sync_nand_and_fetch(pval1, val2); }
^
List of the atomic intrinsics that have this
problem:
__sync_fetch_and_add
__sync_fetch_and_sub
__sync_fetch_and_or
__sync_fetch_and_and
__sync_fetch_and_xor
__sync_fetch_and_nand
__sync_nand_and_fetch
__sync_and_and_fetch
__sync_add_and_fetch
__sync_sub_and_fetch
__sync_or_and_fetch
__sync_xor_and_fetch
__sync_fetch_and_min
__sync_fetch_and_max
__sync_fetch_and_umin
__sync_fetch_and_umax
__sync_val_compare_and_swap
__sync_bool_compare_and_swap
Differential Revision: https://reviews.llvm.org/D83340
Added:
Modified:
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/lib/Sema/SemaChecking.cpp
clang/test/Sema/builtins.c
Removed:
################################################################################
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 71517edd6659..aa4de2812312 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -7939,6 +7939,8 @@ def err_atomic_builtin_pointer_size : Error<
def err_atomic_exclusive_builtin_pointer_size : Error<
"address argument to load or store exclusive builtin must be a pointer to"
" 1,2,4 or 8 byte type (%0 invalid)">;
+def err_atomic_builtin_ext_int_size : Error<
+ "Atomic memory operand must have a power-of-two size">;
def err_atomic_op_needs_atomic : Error<
"address argument to atomic operation must be a pointer to _Atomic "
"type (%0 invalid)">;
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index efaf36a69306..509d88e25000 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -5349,6 +5349,15 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
// gracefully.
TheCall->setType(ResultType);
+ // Prohibit use of _ExtInt with atomic builtins.
+ // The arguments would have already been converted to the first argument's
+ // type, so only need to check the first argument.
+ const auto *ExtIntValType = ValType->getAs<ExtIntType>();
+ if (ExtIntValType && !llvm::isPowerOf2_64(ExtIntValType->getNumBits())) {
+ Diag(FirstArg->getExprLoc(), diag::err_atomic_builtin_ext_int_size);
+ return ExprError();
+ }
+
return TheCallResult;
}
diff --git a/clang/test/Sema/builtins.c b/clang/test/Sema/builtins.c
index 1d41bcf9f086..90c033e47cd1 100644
--- a/clang/test/Sema/builtins.c
+++ b/clang/test/Sema/builtins.c
@@ -281,6 +281,42 @@ void test21(const int *ptr) {
__atomic_fetch_add(ptr, 1, 0); // expected-error {{address argument to atomic operation must be a pointer to non-const type ('const int *' invalid)}}
}
+void test_ei_i42i(_ExtInt(42) *ptr, int value) {
+ __sync_fetch_and_add(ptr, value); // expected-error {{Atomic memory operand must have a power-of-two size}}
+ // expected-warning at +1 {{the semantics of this intrinsic changed with GCC version 4.4 - the newer semantics are provided here}}
+ __sync_nand_and_fetch(ptr, value); // expected-error {{Atomic memory operand must have a power-of-two size}}
+}
+
+void test_ei_i64i(_ExtInt(64) *ptr, int value) {
+ __sync_fetch_and_add(ptr, value); // expect success
+ // expected-warning at +1 {{the semantics of this intrinsic changed with GCC version 4.4 - the newer semantics are provided here}}
+ __sync_nand_and_fetch(ptr, value); // expect success
+}
+
+void test_ei_ii42(int *ptr, _ExtInt(42) value) {
+ __sync_fetch_and_add(ptr, value); // expect success
+ // expected-warning at +1 {{the semantics of this intrinsic changed with GCC version 4.4 - the newer semantics are provided here}}
+ __sync_nand_and_fetch(ptr, value); // expect success
+}
+
+void test_ei_ii64(int *ptr, _ExtInt(64) value) {
+ __sync_fetch_and_add(ptr, value); // expect success
+ // expected-warning at +1 {{the semantics of this intrinsic changed with GCC version 4.4 - the newer semantics are provided here}}
+ __sync_nand_and_fetch(ptr, value); // expect success
+}
+
+void test_ei_i42i42(_ExtInt(42) *ptr, _ExtInt(42) value) {
+ __sync_fetch_and_add(ptr, value); // expected-error {{Atomic memory operand must have a power-of-two size}}
+ // expected-warning at +1 {{the semantics of this intrinsic changed with GCC version 4.4 - the newer semantics are provided here}}
+ __sync_nand_and_fetch(ptr, value); // expected-error {{Atomic memory operand must have a power-of-two size}}
+}
+
+void test_ei_i64i64(_ExtInt(64) *ptr, _ExtInt(64) value) {
+ __sync_fetch_and_add(ptr, value); // expect success
+ // expected-warning at +1 {{the semantics of this intrinsic changed with GCC version 4.4 - the newer semantics are provided here}}
+ __sync_nand_and_fetch(ptr, value); // expect success
+}
+
void test22(void) {
(void)__builtin_signbit(); // expected-error{{too few arguments to function call, expected 1, have 0}}
(void)__builtin_signbit(1.0, 2.0, 3.0); // expected-error{{too many arguments to function call, expected 1, have 3}}
More information about the cfe-commits
mailing list