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; _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
