[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