Added atomic_fetch_min, max, umin, umax intrinsics to clang.
These intrinsics work exactly as all other atomic_fetch_* intrinsics and allow to create *atomicrmw* with ordering.
Updated the clang-extensions document.
Differential Revision: https://reviews.llvm.org/D46386
llvm-svn: 332193
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index e3dbf0b..74ecf5f 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -3260,6 +3260,7 @@
Op == AtomicExpr::AO__atomic_exchange_n ||
Op == AtomicExpr::AO__atomic_compare_exchange_n;
bool IsAddSub = false;
+ bool IsMinMax = false;
switch (Op) {
case AtomicExpr::AO__c11_atomic_init:
@@ -3313,6 +3314,12 @@
Form = Arithmetic;
break;
+ case AtomicExpr::AO__atomic_fetch_min:
+ case AtomicExpr::AO__atomic_fetch_max:
+ IsMinMax = true;
+ Form = Arithmetic;
+ break;
+
case AtomicExpr::AO__c11_atomic_exchange:
case AtomicExpr::AO__opencl_atomic_exchange:
case AtomicExpr::AO__atomic_exchange_n:
@@ -3395,12 +3402,21 @@
// For an arithmetic operation, the implied arithmetic must be well-formed.
if (Form == Arithmetic) {
// gcc does not enforce these rules for GNU atomics, but we do so for sanity.
- if (IsAddSub && !ValType->isIntegerType() && !ValType->isPointerType()) {
+ if (IsAddSub && !ValType->isIntegerType()
+ && !ValType->isPointerType()) {
Diag(DRE->getLocStart(), diag::err_atomic_op_needs_atomic_int_or_ptr)
<< IsC11 << Ptr->getType() << Ptr->getSourceRange();
return ExprError();
}
- if (!IsAddSub && !ValType->isIntegerType()) {
+ if (IsMinMax) {
+ const BuiltinType *BT = ValType->getAs<BuiltinType>();
+ if (!BT || (BT->getKind() != BuiltinType::Int &&
+ BT->getKind() != BuiltinType::UInt)) {
+ Diag(DRE->getLocStart(), diag::err_atomic_op_needs_int32_or_ptr);
+ return ExprError();
+ }
+ }
+ if (!IsAddSub && !IsMinMax && !ValType->isIntegerType()) {
Diag(DRE->getLocStart(), diag::err_atomic_op_bitwise_needs_atomic_int)
<< IsC11 << Ptr->getType() << Ptr->getSourceRange();
return ExprError();