[clang] 5f3462d - [clang] builtins for atomicrmw fminmax/_num (#187139)
via cfe-commits
cfe-commits at lists.llvm.org
Sun Jun 28 09:15:30 PDT 2026
Author: gonzalobg
Date: 2026-06-28T18:15:26+02:00
New Revision: 5f3462d9aa5dce3314738b892f14a78dced93d25
URL: https://github.com/llvm/llvm-project/commit/5f3462d9aa5dce3314738b892f14a78dced93d25
DIFF: https://github.com/llvm/llvm-project/commit/5f3462d9aa5dce3314738b892f14a78dced93d25.diff
LOG: [clang] builtins for atomicrmw fminmax/_num (#187139)
Adds compiler builtins for `atomicrmw`: `fminimum`, `fmaximum`,
`fminimum_num`, `fmaximum_num`.
These will be used by the corresponding libc++ atomic apis (see #186716).
Added:
Modified:
clang/include/clang/Basic/Builtins.td
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/lib/AST/Expr.cpp
clang/lib/CodeGen/CGAtomic.cpp
clang/lib/Sema/SemaChecking.cpp
clang/test/CodeGen/AArch64/atomic-ops-float-check-minmax.c
clang/test/Sema/atomic-ops.c
clang/test/Sema/scoped-atomic-ops.c
Removed:
################################################################################
diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index 63cdb787bea16..87ba4c6c17efd 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -2515,6 +2515,30 @@ def ScopedAtomicFetchMax : AtomicBuiltin {
let Prototype = "void(...)";
}
+def ScopedAtomicFetchFMinimum : AtomicBuiltin {
+ let Spellings = ["__scoped_atomic_fetch_fminimum"];
+ let Attributes = [CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
+def ScopedAtomicFetchFMaximum : AtomicBuiltin {
+ let Spellings = ["__scoped_atomic_fetch_fmaximum"];
+ let Attributes = [CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
+def ScopedAtomicFetchFMinimumNum : AtomicBuiltin {
+ let Spellings = ["__scoped_atomic_fetch_fminimum_num"];
+ let Attributes = [CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
+def ScopedAtomicFetchFMaximumNum : AtomicBuiltin {
+ let Spellings = ["__scoped_atomic_fetch_fmaximum_num"];
+ let Attributes = [CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
def ScopedAtomicAddFetch : AtomicBuiltin {
let Spellings = ["__scoped_atomic_add_fetch"];
let Attributes = [CustomTypeChecking];
@@ -2667,6 +2691,30 @@ def AtomicFetchMin : AtomicBuiltin {
let Prototype = "void(...)";
}
+def AtomicFetchFMinimum : AtomicBuiltin {
+ let Spellings = ["__atomic_fetch_fminimum"];
+ let Attributes = [CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
+def AtomicFetchFMaximum : AtomicBuiltin {
+ let Spellings = ["__atomic_fetch_fmaximum"];
+ let Attributes = [CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
+def AtomicFetchFMinimumNum : AtomicBuiltin {
+ let Spellings = ["__atomic_fetch_fminimum_num"];
+ let Attributes = [CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
+def AtomicFetchFMaximumNum : AtomicBuiltin {
+ let Spellings = ["__atomic_fetch_fmaximum_num"];
+ let Attributes = [CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
def AtomicFetchUInc : AtomicBuiltin {
let Spellings = ["__atomic_fetch_uinc"];
let Attributes = [CustomTypeChecking];
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 7e20630708312..1135b5a3672f0 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -9671,6 +9671,9 @@ def err_atomic_op_needs_atomic_int_or_fp : Error<
def err_atomic_op_needs_atomic_int : Error<
"address argument to atomic operation must be a pointer to "
"%select{|atomic }0integer (%1 invalid)">;
+def err_atomic_op_needs_atomic_fp
+ : Error<"address argument to atomic operation must be a pointer to "
+ "%select{|atomic }0floating point type (%1 invalid)">;
def warn_atomic_op_has_invalid_memory_order : Warning<
"%select{|success |failure }0memory order argument to atomic operation is invalid">,
InGroup<DiagGroup<"atomic-memory-ordering">>;
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 614fae99321f8..cec733556dc91 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -5318,6 +5318,10 @@ unsigned AtomicExpr::getNumSubExprs(AtomicOp Op) {
case AO__atomic_max_fetch:
case AO__atomic_fetch_min:
case AO__atomic_fetch_max:
+ case AO__atomic_fetch_fminimum:
+ case AO__atomic_fetch_fmaximum:
+ case AO__atomic_fetch_fminimum_num:
+ case AO__atomic_fetch_fmaximum_num:
case AO__atomic_fetch_uinc:
case AO__atomic_fetch_udec:
return 3;
@@ -5341,6 +5345,10 @@ unsigned AtomicExpr::getNumSubExprs(AtomicOp Op) {
case AO__scoped_atomic_max_fetch:
case AO__scoped_atomic_fetch_min:
case AO__scoped_atomic_fetch_max:
+ case AO__scoped_atomic_fetch_fminimum:
+ case AO__scoped_atomic_fetch_fmaximum:
+ case AO__scoped_atomic_fetch_fminimum_num:
+ case AO__scoped_atomic_fetch_fmaximum_num:
case AO__scoped_atomic_exchange_n:
case AO__scoped_atomic_fetch_uinc:
case AO__scoped_atomic_fetch_udec:
diff --git a/clang/lib/CodeGen/CGAtomic.cpp b/clang/lib/CodeGen/CGAtomic.cpp
index 270965b109943..61e13d4925020 100644
--- a/clang/lib/CodeGen/CGAtomic.cpp
+++ b/clang/lib/CodeGen/CGAtomic.cpp
@@ -536,7 +536,6 @@ static llvm::Value *EmitPostAtomicMinMax(CGBuilderTy &Builder,
Op == AtomicExpr::AO__scoped_atomic_max_fetch)
? llvm::Intrinsic::maxnum
: llvm::Intrinsic::minnum;
-
return Builder.CreateBinaryIntrinsic(IID, OldVal, RHS, llvm::FMFSource(),
"newval");
}
@@ -707,6 +706,20 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest,
: llvm::AtomicRMWInst::UMin);
break;
+ case AtomicExpr::AO__atomic_fetch_fminimum:
+ case AtomicExpr::AO__scoped_atomic_fetch_fminimum:
+ assert(E->getValueType()->isFloatingType() &&
+ "fminimum operations only support floating-point types");
+ Op = llvm::AtomicRMWInst::FMinimum;
+ break;
+
+ case AtomicExpr::AO__atomic_fetch_fminimum_num:
+ case AtomicExpr::AO__scoped_atomic_fetch_fminimum_num:
+ assert(E->getValueType()->isFloatingType() &&
+ "fminimum_num operations only support floating-point types");
+ Op = llvm::AtomicRMWInst::FMinimumNum;
+ break;
+
case AtomicExpr::AO__atomic_max_fetch:
case AtomicExpr::AO__scoped_atomic_max_fetch:
PostOpMinMax = true;
@@ -723,6 +736,20 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest,
: llvm::AtomicRMWInst::UMax);
break;
+ case AtomicExpr::AO__atomic_fetch_fmaximum:
+ case AtomicExpr::AO__scoped_atomic_fetch_fmaximum:
+ assert(E->getValueType()->isFloatingType() &&
+ "fmaximum operations only support floating-point types");
+ Op = llvm::AtomicRMWInst::FMaximum;
+ break;
+
+ case AtomicExpr::AO__atomic_fetch_fmaximum_num:
+ case AtomicExpr::AO__scoped_atomic_fetch_fmaximum_num:
+ assert(E->getValueType()->isFloatingType() &&
+ "fmaximum_num operations only support floating-point types");
+ Op = llvm::AtomicRMWInst::FMaximumNum;
+ break;
+
case AtomicExpr::AO__atomic_and_fetch:
case AtomicExpr::AO__scoped_atomic_and_fetch:
PostOp = llvm::Instruction::And;
@@ -1049,6 +1076,10 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
case AtomicExpr::AO__scoped_atomic_fetch_max:
case AtomicExpr::AO__scoped_atomic_fetch_min:
case AtomicExpr::AO__scoped_atomic_fetch_sub:
+ case AtomicExpr::AO__scoped_atomic_fetch_fminimum:
+ case AtomicExpr::AO__scoped_atomic_fetch_fmaximum:
+ case AtomicExpr::AO__scoped_atomic_fetch_fminimum_num:
+ case AtomicExpr::AO__scoped_atomic_fetch_fmaximum_num:
case AtomicExpr::AO__scoped_atomic_add_fetch:
case AtomicExpr::AO__scoped_atomic_max_fetch:
case AtomicExpr::AO__scoped_atomic_min_fetch:
@@ -1095,6 +1126,10 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
case AtomicExpr::AO__scoped_atomic_exchange_n:
case AtomicExpr::AO__scoped_atomic_fetch_uinc:
case AtomicExpr::AO__scoped_atomic_fetch_udec:
+ case AtomicExpr::AO__atomic_fetch_fminimum:
+ case AtomicExpr::AO__atomic_fetch_fmaximum:
+ case AtomicExpr::AO__atomic_fetch_fminimum_num:
+ case AtomicExpr::AO__atomic_fetch_fmaximum_num:
Val1 = EmitValToTemp(*this, E->getVal1());
break;
}
@@ -1294,6 +1329,14 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
case AtomicExpr::AO__opencl_atomic_fetch_max:
case AtomicExpr::AO__scoped_atomic_fetch_max:
case AtomicExpr::AO__scoped_atomic_max_fetch:
+ case AtomicExpr::AO__atomic_fetch_fminimum:
+ case AtomicExpr::AO__atomic_fetch_fmaximum:
+ case AtomicExpr::AO__atomic_fetch_fminimum_num:
+ case AtomicExpr::AO__atomic_fetch_fmaximum_num:
+ case AtomicExpr::AO__scoped_atomic_fetch_fminimum:
+ case AtomicExpr::AO__scoped_atomic_fetch_fmaximum:
+ case AtomicExpr::AO__scoped_atomic_fetch_fminimum_num:
+ case AtomicExpr::AO__scoped_atomic_fetch_fmaximum_num:
case AtomicExpr::AO__scoped_atomic_fetch_uinc:
case AtomicExpr::AO__scoped_atomic_fetch_udec:
case AtomicExpr::AO__atomic_test_and_set:
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index c3ca45ee55786..d3eb71e1afe88 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -5010,6 +5010,7 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange,
AOEVT_None = 0,
AOEVT_Pointer = 1,
AOEVT_FP = 2,
+ AOEVT_Int = 4,
};
unsigned ArithAllows = AOEVT_None;
@@ -5061,6 +5062,17 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange,
ArithAllows = AOEVT_Pointer | AOEVT_FP;
Form = Arithmetic;
break;
+ case AtomicExpr::AO__atomic_fetch_fminimum:
+ case AtomicExpr::AO__atomic_fetch_fmaximum:
+ case AtomicExpr::AO__atomic_fetch_fminimum_num:
+ case AtomicExpr::AO__atomic_fetch_fmaximum_num:
+ case AtomicExpr::AO__scoped_atomic_fetch_fminimum:
+ case AtomicExpr::AO__scoped_atomic_fetch_fmaximum:
+ case AtomicExpr::AO__scoped_atomic_fetch_fminimum_num:
+ case AtomicExpr::AO__scoped_atomic_fetch_fmaximum_num:
+ ArithAllows = AOEVT_FP;
+ Form = Arithmetic;
+ break;
case AtomicExpr::AO__atomic_fetch_max:
case AtomicExpr::AO__atomic_fetch_min:
case AtomicExpr::AO__atomic_max_fetch:
@@ -5075,7 +5087,7 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange,
case AtomicExpr::AO__opencl_atomic_fetch_min:
case AtomicExpr::AO__hip_atomic_fetch_max:
case AtomicExpr::AO__hip_atomic_fetch_min:
- ArithAllows = AOEVT_FP;
+ ArithAllows = AOEVT_Int | AOEVT_FP;
Form = Arithmetic;
break;
case AtomicExpr::AO__c11_atomic_fetch_and:
@@ -5253,7 +5265,9 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange,
&Context.getTargetInfo().getLongDoubleFormat() ==
&llvm::APFloat::x87DoubleExtended();
if (ValType->isIntegerType())
- return true;
+ // Special case: f-prefixed operations (AOEVT_FP exactly) reject
+ // integers. Explicit AOEVT_Int or other combinations allow integers.
+ return (AllowedType & AOEVT_Int) || AllowedType != AOEVT_FP;
if (ValType->isPointerType())
return AllowedType & AOEVT_Pointer;
if (!(ValType->isFloatingType() && (AllowedType & AOEVT_FP)))
@@ -5264,13 +5278,16 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange,
return true;
};
if (!IsAllowedValueType(ValType, ArithAllows)) {
- auto DID = ArithAllows & AOEVT_FP
+ auto DID =
+ ArithAllows == AOEVT_FP
+ ? diag::err_atomic_op_needs_atomic_fp
+ : (ArithAllows & AOEVT_FP
? (ArithAllows & AOEVT_Pointer
? diag::err_atomic_op_needs_atomic_int_ptr_or_fp
: diag::err_atomic_op_needs_atomic_int_or_fp)
: (ArithAllows & AOEVT_Pointer
? diag::err_atomic_op_needs_atomic_int_or_ptr
- : diag::err_atomic_op_needs_atomic_int);
+ : diag::err_atomic_op_needs_atomic_int));
Diag(ExprRange.getBegin(), DID)
<< IsC11 << Ptr->getType() << Ptr->getSourceRange();
return ExprError();
diff --git a/clang/test/CodeGen/AArch64/atomic-ops-float-check-minmax.c b/clang/test/CodeGen/AArch64/atomic-ops-float-check-minmax.c
index 3bf5cddb160e4..2a646ad1c6996 100644
--- a/clang/test/CodeGen/AArch64/atomic-ops-float-check-minmax.c
+++ b/clang/test/CodeGen/AArch64/atomic-ops-float-check-minmax.c
@@ -115,3 +115,20 @@ void test_minmax_postop(float *f32, _Float16 *f16, __bf16 *bf16, double *f64) {
*f16 = __atomic_min_fetch(f16, 42.1, memory_order_release);
*bf16 = __atomic_min_fetch(bf16, 42.1, memory_order_release);
}
+
+// CHECK-LABEL: define dso_local void @test_fetch_variants(
+// CHECK-SAME: ptr noundef [[F64:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK: [[TMP0:%.*]] = atomicrmw fminimum ptr {{%.*}}, double {{%.*}} release, align 8
+// CHECK: [[TMP1:%.*]] = atomicrmw fmaximum ptr {{%.*}}, double {{%.*}} release, align 8
+// CHECK: [[TMP2:%.*]] = atomicrmw fminimumnum ptr {{%.*}}, double {{%.*}} release, align 8
+// CHECK: [[TMP3:%.*]] = atomicrmw fmaximumnum ptr {{%.*}}, double {{%.*}} release, align 8
+// CHECK-NOT: call {{.*}} @llvm.minimum
+// CHECK-NOT: call {{.*}} @llvm.maximum
+// CHECK-NOT: call {{.*}} @llvm.minimumnum
+// CHECK-NOT: call {{.*}} @llvm.maximumnum
+void test_fetch_variants(double *f64) {
+ double old1 = __atomic_fetch_fminimum(f64, 42.1, memory_order_release);
+ double old2 = __atomic_fetch_fmaximum(f64, 42.1, memory_order_release);
+ double old3 = __atomic_fetch_fminimum_num(f64, 42.1, memory_order_release);
+ double old4 = __atomic_fetch_fmaximum_num(f64, 42.1, memory_order_release);
+}
diff --git a/clang/test/Sema/atomic-ops.c b/clang/test/Sema/atomic-ops.c
index 3318e369f3e0d..a3bc8d2ec75e7 100644
--- a/clang/test/Sema/atomic-ops.c
+++ b/clang/test/Sema/atomic-ops.c
@@ -252,6 +252,18 @@ void f(_Atomic(int) *i, const _Atomic(int) *ci,
__atomic_fetch_max(D, 3, memory_order_seq_cst);
__atomic_fetch_max(P, 3, memory_order_seq_cst); // expected-error {{must be a pointer to integer or supported floating point type}}
__atomic_fetch_max(p, 3); // expected-error {{too few arguments to function call, expected 3, have 2}}
+ __atomic_fetch_fminimum(F, 3, memory_order_seq_cst);
+ __atomic_fetch_fminimum(D, 3, memory_order_seq_cst);
+ __atomic_fetch_fmaximum(F, 3, memory_order_seq_cst);
+ __atomic_fetch_fmaximum(D, 3, memory_order_seq_cst);
+ __atomic_fetch_fmaximum(P, 3, memory_order_seq_cst); // expected-error {{must be a pointer to floating point type}}
+ __atomic_fetch_fmaximum(p, 3); // expected-error {{too few arguments to function call, expected 3, have 2}}
+ __atomic_fetch_fminimum_num(F, 3, memory_order_seq_cst);
+ __atomic_fetch_fminimum_num(D, 3, memory_order_seq_cst);
+ __atomic_fetch_fmaximum_num(F, 3, memory_order_seq_cst);
+ __atomic_fetch_fmaximum_num(D, 3, memory_order_seq_cst);
+ __atomic_fetch_fmaximum_num(P, 3, memory_order_seq_cst); // expected-error {{must be a pointer to floating point type}}
+ __atomic_fetch_fmaximum_num(p, 3); // expected-error {{too few arguments to function call, expected 3, have 2}}
__atomic_fetch_uinc(F, 1, memory_order_seq_cst); // expected-error {{address argument to atomic operation must be a pointer to integer}}
__atomic_fetch_udec(F, 1, memory_order_seq_cst); // expected-error {{address argument to atomic operation must be a pointer to integer}}
@@ -388,7 +400,7 @@ void PR16931(int* x) { // expected-note {{passing argument to parameter 'x' here
PR16931(&flagvar); // expected-error {{incompatible pointer types}}
}
-void memory_checks(_Atomic(int) *Ap, int *p, int val) {
+void memory_checks(_Atomic(int) *Ap, int *p, int val, float *fp, float fval) {
(void)__c11_atomic_load(Ap, memory_order_relaxed);
(void)__c11_atomic_load(Ap, memory_order_acquire);
(void)__c11_atomic_load(Ap, memory_order_consume);
@@ -601,6 +613,20 @@ void memory_checks(_Atomic(int) *Ap, int *p, int val) {
(void)__atomic_fetch_min(p, val, memory_order_acq_rel);
(void)__atomic_fetch_min(p, val, memory_order_seq_cst);
+ (void)__atomic_fetch_fminimum(fp, fval, memory_order_relaxed);
+ (void)__atomic_fetch_fminimum(fp, fval, memory_order_acquire);
+ (void)__atomic_fetch_fminimum(fp, fval, memory_order_consume);
+ (void)__atomic_fetch_fminimum(fp, fval, memory_order_release);
+ (void)__atomic_fetch_fminimum(fp, fval, memory_order_acq_rel);
+ (void)__atomic_fetch_fminimum(fp, fval, memory_order_seq_cst);
+
+ (void)__atomic_fetch_fminimum_num(fp, fval, memory_order_relaxed);
+ (void)__atomic_fetch_fminimum_num(fp, fval, memory_order_acquire);
+ (void)__atomic_fetch_fminimum_num(fp, fval, memory_order_consume);
+ (void)__atomic_fetch_fminimum_num(fp, fval, memory_order_release);
+ (void)__atomic_fetch_fminimum_num(fp, fval, memory_order_acq_rel);
+ (void)__atomic_fetch_fminimum_num(fp, fval, memory_order_seq_cst);
+
(void)__atomic_fetch_uinc(p, val, memory_order_relaxed);
(void)__atomic_fetch_uinc(p, val, memory_order_acquire);
(void)__atomic_fetch_uinc(p, val, memory_order_consume);
@@ -622,6 +648,20 @@ void memory_checks(_Atomic(int) *Ap, int *p, int val) {
(void)__atomic_fetch_max(p, val, memory_order_acq_rel);
(void)__atomic_fetch_max(p, val, memory_order_seq_cst);
+ (void)__atomic_fetch_fmaximum(fp, fval, memory_order_relaxed);
+ (void)__atomic_fetch_fmaximum(fp, fval, memory_order_acquire);
+ (void)__atomic_fetch_fmaximum(fp, fval, memory_order_consume);
+ (void)__atomic_fetch_fmaximum(fp, fval, memory_order_release);
+ (void)__atomic_fetch_fmaximum(fp, fval, memory_order_acq_rel);
+ (void)__atomic_fetch_fmaximum(fp, fval, memory_order_seq_cst);
+
+ (void)__atomic_fetch_fmaximum_num(fp, fval, memory_order_relaxed);
+ (void)__atomic_fetch_fmaximum_num(fp, fval, memory_order_acquire);
+ (void)__atomic_fetch_fmaximum_num(fp, fval, memory_order_consume);
+ (void)__atomic_fetch_fmaximum_num(fp, fval, memory_order_release);
+ (void)__atomic_fetch_fmaximum_num(fp, fval, memory_order_acq_rel);
+ (void)__atomic_fetch_fmaximum_num(fp, fval, memory_order_seq_cst);
+
(void)__atomic_and_fetch(p, val, memory_order_relaxed);
(void)__atomic_and_fetch(p, val, memory_order_acquire);
(void)__atomic_and_fetch(p, val, memory_order_consume);
@@ -664,6 +704,7 @@ void memory_checks(_Atomic(int) *Ap, int *p, int val) {
(void)__atomic_min_fetch(p, val, memory_order_acq_rel);
(void)__atomic_min_fetch(p, val, memory_order_seq_cst);
+
(void)__atomic_exchange_n(p, val, memory_order_relaxed);
(void)__atomic_exchange_n(p, val, memory_order_acquire);
(void)__atomic_exchange_n(p, val, memory_order_consume);
@@ -851,6 +892,14 @@ void nullPointerWarning(void) {
(void)__atomic_fetch_min((int*)0, 42, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
(void)__atomic_fetch_max((volatile int*)0, 42, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
(void)__atomic_fetch_max((int*)0, 42, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__atomic_fetch_fminimum((volatile float*)0, 42, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__atomic_fetch_fminimum((float*)0, 42, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__atomic_fetch_fmaximum((volatile float*)0, 42, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__atomic_fetch_fmaximum((float*)0, 42, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__atomic_fetch_fminimum_num((volatile float*)0, 42, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__atomic_fetch_fminimum_num((float*)0, 42, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__atomic_fetch_fmaximum_num((volatile float*)0, 42, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ (void)__atomic_fetch_fmaximum_num((float*)0, 42, memory_order_relaxed); // expected-warning {{null passed to a callee that requires a non-null argument}}
// These don't warn: the "desired" parameter is passed by value. Even for
// atomic pointers the "desired" result can be NULL.
diff --git a/clang/test/Sema/scoped-atomic-ops.c b/clang/test/Sema/scoped-atomic-ops.c
index 49ddc64ce23eb..716cf14d0b4a3 100644
--- a/clang/test/Sema/scoped-atomic-ops.c
+++ b/clang/test/Sema/scoped-atomic-ops.c
@@ -93,6 +93,38 @@ void fi3e(float *a, float *b, float *c, float *d, float *e, float *f) {
*e = __scoped_atomic_fetch_udec(e, 1u, __ATOMIC_RELAXED, 42); // expected-error {{address argument to atomic operation must be a pointer to integer ('float *' invalid)}}
}
+void fi3f(float *a, float *b, float *c, float *d, double *e, double *f, double *g, double *h) {
+ *a = __scoped_atomic_fetch_fminimum(a, 1.0f, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM);
+ *b = __scoped_atomic_fetch_fmaximum(b, 1.0f, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM);
+ *c = __scoped_atomic_fetch_fminimum_num(c, 1.0f, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM);
+ *d = __scoped_atomic_fetch_fmaximum_num(d, 1.0f, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM);
+ *e = __scoped_atomic_fetch_fminimum(e, 1.0, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM);
+ *f = __scoped_atomic_fetch_fmaximum(f, 1.0, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM);
+ *g = __scoped_atomic_fetch_fminimum_num(g, 1.0, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM);
+ *h = __scoped_atomic_fetch_fmaximum_num(h, 1.0, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM);
+}
+
+void fi3g(float *a, float *b, float *c, float *d) {
+ *a = __scoped_atomic_fetch_fminimum(a, 1.0f, __ATOMIC_RELAXED); // expected-error {{too few arguments to function call, expected 4, have 3}}
+ *b = __scoped_atomic_fetch_fmaximum(b, 1.0f, __ATOMIC_RELAXED); // expected-error {{too few arguments to function call, expected 4, have 3}}
+ *c = __scoped_atomic_fetch_fminimum_num(c, 1.0f, __ATOMIC_RELAXED); // expected-error {{too few arguments to function call, expected 4, have 3}}
+ *d = __scoped_atomic_fetch_fmaximum_num(d, 1.0f, __ATOMIC_RELAXED); // expected-error {{too few arguments to function call, expected 4, have 3}}
+}
+
+void fi3h(float *a, float *b, float *c, float *d) {
+ *a = __scoped_atomic_fetch_fminimum(a, 1.0f, __ATOMIC_RELAXED, 42); // expected-error {{synchronization scope argument to atomic operation is invalid}}
+ *b = __scoped_atomic_fetch_fmaximum(b, 1.0f, __ATOMIC_RELAXED, 42); // expected-error {{synchronization scope argument to atomic operation is invalid}}
+ *c = __scoped_atomic_fetch_fminimum_num(c, 1.0f, __ATOMIC_RELAXED, 42); // expected-error {{synchronization scope argument to atomic operation is invalid}}
+ *d = __scoped_atomic_fetch_fmaximum_num(d, 1.0f, __ATOMIC_RELAXED, 42); // expected-error {{synchronization scope argument to atomic operation is invalid}}
+}
+
+void fi3i(int *a, int *b, int *c, int *d) {
+ *a = __scoped_atomic_fetch_fminimum(a, 1.0f, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM); // expected-error {{address argument to atomic operation must be a pointer to floating point type}}
+ *b = __scoped_atomic_fetch_fmaximum(b, 1.0f, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM); // expected-error {{address argument to atomic operation must be a pointer to floating point type}}
+ *c = __scoped_atomic_fetch_fminimum_num(c, 1.0f, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM); // expected-error {{address argument to atomic operation must be a pointer to floating point type}}
+ *d = __scoped_atomic_fetch_fmaximum_num(d, 1.0f, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM); // expected-error {{address argument to atomic operation must be a pointer to floating point type}}
+}
+
int fi4a(int *i) {
int cmp = 0;
int desired = 1;
More information about the cfe-commits
mailing list