[clang] [Clang] Permit floating point values in atomic_*_n operations (PR #183843)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Feb 27 13:46:55 PST 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Joseph Huber (jhuber6)
<details>
<summary>Changes</summary>
Summary:
We already support floating point arguments for the standard atomic
functions. I do not know if this was an oversight or a conscious choice,
but this was not applied to the `_n` extensions. This PR permits it for
non-x87 floating point types, as these are all power of two primitive
types smaller than 16 bytes.
---
Full diff: https://github.com/llvm/llvm-project/pull/183843.diff
3 Files Affected:
- (modified) clang/lib/Sema/SemaChecking.cpp (+6-2)
- (modified) clang/test/Sema/atomic-ops.c (+12-6)
- (modified) clang/test/Sema/scoped-atomic-ops.c (+26)
``````````diff
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 45dce52179f82..b6e0174071424 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -4894,10 +4894,14 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange,
diag::err_incomplete_type)) {
return ExprError();
}
- } else if (IsN && !ValType->isIntegerType() && !ValType->isPointerType()) {
+ } else if (IsN && !ValType->isIntegerType() && !ValType->isPointerType() &&
+ !(ValType->isFloatingType() &&
+ !(ValType->isSpecificBuiltinType(BuiltinType::LongDouble) &&
+ &Context.getTargetInfo().getLongDoubleFormat() ==
+ &llvm::APFloat::x87DoubleExtended()))) {
// For __atomic_*_n operations, the value type must be a scalar integral or
// pointer type which is 1, 2, 4, 8 or 16 bytes in length.
- Diag(ExprRange.getBegin(), diag::err_atomic_op_needs_atomic_int_or_ptr)
+ Diag(ExprRange.getBegin(), diag::err_atomic_op_needs_atomic_int_ptr_or_fp)
<< IsC11 << Ptr->getType() << Ptr->getSourceRange();
return ExprError();
}
diff --git a/clang/test/Sema/atomic-ops.c b/clang/test/Sema/atomic-ops.c
index 0e39777a0172c..f14475584c1d2 100644
--- a/clang/test/Sema/atomic-ops.c
+++ b/clang/test/Sema/atomic-ops.c
@@ -156,7 +156,8 @@ void f(_Atomic(int) *i, const _Atomic(int) *ci,
_Atomic(int*) *p, _Atomic(float) *f, _Atomic(double) *d,
_Atomic(long double) *ld,
int *I, const int *CI,
- int **P, float *F, double *D, struct S *s1, struct S *s2) {
+ int **P, float *F, double *D, long double *LD,
+ struct S *s1, struct S *s2) {
__c11_atomic_init(I, 5); // expected-error {{pointer to _Atomic}}
__c11_atomic_init(ci, 5); // expected-error {{address argument to atomic operation must be a pointer to non-const _Atomic type ('const _Atomic(int) *' invalid)}}
@@ -174,8 +175,10 @@ void f(_Atomic(int) *i, const _Atomic(int) *ci,
int load_n_1 = __atomic_load_n(I, memory_order_relaxed);
int *load_n_2 = __atomic_load_n(P, memory_order_relaxed);
- float load_n_3 = __atomic_load_n(D, memory_order_relaxed); // expected-error {{must be a pointer to integer or pointer}}
- __atomic_load_n(s1, memory_order_relaxed); // expected-error {{must be a pointer to integer or pointer}}
+ double load_n_3 = __atomic_load_n(D, memory_order_relaxed);
+ float load_n_4 = __atomic_load_n(F, memory_order_relaxed);
+ __atomic_load_n(LD, memory_order_relaxed); // fp80-error {{must be a pointer to integer, pointer or supported floating point type}}
+ __atomic_load_n(s1, memory_order_relaxed); // expected-error {{must be a pointer to integer, pointer or supported floating point type}}
load_n_1 = __atomic_load_n(CI, memory_order_relaxed);
__atomic_load(i, I, memory_order_relaxed); // expected-error {{must be a pointer to a trivially-copyable type}}
@@ -198,8 +201,10 @@ void f(_Atomic(int) *i, const _Atomic(int) *ci,
__atomic_store_n(I, 4.0, memory_order_release);
__atomic_store_n(CI, 4, memory_order_release); // expected-error {{address argument to atomic operation must be a pointer to non-const type ('const int *' invalid)}}
__atomic_store_n(I, P, memory_order_release); // expected-error {{parameter of type 'int'}}
- __atomic_store_n(i, 1, memory_order_release); // expected-error {{must be a pointer to integer or pointer}}
- __atomic_store_n(s1, *s2, memory_order_release); // expected-error {{must be a pointer to integer or pointer}}
+ __atomic_store_n(i, 1, memory_order_release); // expected-error {{must be a pointer to integer, pointer or supported floating point type}}
+ __atomic_store_n(s1, *s2, memory_order_release); // expected-error {{must be a pointer to integer, pointer or supported floating point type}}
+ __atomic_store_n(D, 1.0, memory_order_release);
+ __atomic_store_n(F, 1.0f, memory_order_release);
__atomic_store_n(I, I, memory_order_release); // expected-error {{incompatible pointer to integer conversion passing 'int *' to parameter of type 'int'; dereference with *}}
__atomic_store(I, *P, memory_order_release);
@@ -209,7 +214,8 @@ void f(_Atomic(int) *i, const _Atomic(int) *ci,
int exchange_1 = __c11_atomic_exchange(i, 1, memory_order_seq_cst);
int exchange_2 = __c11_atomic_exchange(I, 1, memory_order_seq_cst); // expected-error {{must be a pointer to _Atomic}}
- int exchange_3 = __atomic_exchange_n(i, 1, memory_order_seq_cst); // expected-error {{must be a pointer to integer or pointer}}
+ int exchange_3 = __atomic_exchange_n(i, 1, memory_order_seq_cst); // expected-error {{must be a pointer to integer, pointer or supported floating point type}}
+ double exchange_5 = __atomic_exchange_n(D, 2.0, memory_order_seq_cst);
int exchange_4 = __atomic_exchange_n(I, 1, memory_order_seq_cst);
__atomic_exchange(s1, s2, s2, memory_order_seq_cst);
diff --git a/clang/test/Sema/scoped-atomic-ops.c b/clang/test/Sema/scoped-atomic-ops.c
index 267c913dc9f9f..ea054af138ee0 100644
--- a/clang/test/Sema/scoped-atomic-ops.c
+++ b/clang/test/Sema/scoped-atomic-ops.c
@@ -117,3 +117,29 @@ int fi7a(_Bool *c) {
return __scoped_atomic_exchange_n(c, 1, __ATOMIC_RELAXED,
__MEMORY_SCOPE_SYSTEM);
}
+
+float ff1a(float *i) {
+ float cmp = 0;
+ float desired = 1;
+ return __scoped_atomic_compare_exchange(i, &cmp, &desired, 0,
+ __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE,
+ __MEMORY_SCOPE_SYSTEM);
+}
+
+float ff2a(float *i) {
+ float cmp = 0;
+ return __scoped_atomic_compare_exchange_n(i, &cmp, 1, 1, __ATOMIC_ACQUIRE,
+ __ATOMIC_ACQUIRE,
+ __MEMORY_SCOPE_SYSTEM);
+}
+
+float ff3a(float *c, float *d) {
+ float ret;
+ __scoped_atomic_exchange(c, d, &ret, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM);
+ return ret;
+}
+
+float ff4a(_Bool *c) {
+ return __scoped_atomic_exchange_n(c, 1, __ATOMIC_RELAXED,
+ __MEMORY_SCOPE_SYSTEM);
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/183843
More information about the cfe-commits
mailing list