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@+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@+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@+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@+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@+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@+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}} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits