aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Sema/SemaChecking.cpp
diff options
context:
space:
mode:
authorFangrui Song <i@maskray.me>2023-12-14 11:03:28 -0800
committerGitHub <noreply@github.com>2023-12-14 11:03:28 -0800
commitfed564432cef76f8b303c19ab1dfc0a14878fbc3 (patch)
treeffa392c614b3c37bfc7a30f962395e28642f5d9b /clang/lib/Sema/SemaChecking.cpp
parent419c45a3252489d0ebac4535fe5a4ed9a6af6bbd (diff)
downloadllvm-fed564432cef76f8b303c19ab1dfc0a14878fbc3.zip
llvm-fed564432cef76f8b303c19ab1dfc0a14878fbc3.tar.gz
llvm-fed564432cef76f8b303c19ab1dfc0a14878fbc3.tar.bz2
[Sema] atomic_compare_exchange: check failure memory order (#74959)
For `__atomic_compare_exchange{,_n}/__c11_atomic_compare_exchange_{strong,weak}`, GCC checks both the success memory order and the failure memory order under the default -Winvalid-memory-model ("memory model" is confusing here and "memory order" is much more common in the atomic context). * The failure memory order, if a constant, must be one of relaxed/consume/acquire/seq_cst. Clang checks just the success memory order under the default -Watomic-memory-ordering. This patch checks the failure memory order.
Diffstat (limited to 'clang/lib/Sema/SemaChecking.cpp')
-rw-r--r--clang/lib/Sema/SemaChecking.cpp34
1 files changed, 26 insertions, 8 deletions
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 254c272..bcddaa1 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -5030,14 +5030,14 @@ bool Sema::CheckAMDGCNBuiltinFunctionCall(unsigned BuiltinID,
if (!llvm::isValidAtomicOrderingCABI(Ord))
return Diag(ArgExpr->getBeginLoc(),
diag::warn_atomic_op_has_invalid_memory_order)
- << ArgExpr->getSourceRange();
+ << 0 << ArgExpr->getSourceRange();
switch (static_cast<llvm::AtomicOrderingCABI>(Ord)) {
case llvm::AtomicOrderingCABI::relaxed:
case llvm::AtomicOrderingCABI::consume:
if (BuiltinID == AMDGPU::BI__builtin_amdgcn_fence)
return Diag(ArgExpr->getBeginLoc(),
diag::warn_atomic_op_has_invalid_memory_order)
- << ArgExpr->getSourceRange();
+ << 0 << ArgExpr->getSourceRange();
break;
case llvm::AtomicOrderingCABI::acquire:
case llvm::AtomicOrderingCABI::release:
@@ -8177,13 +8177,31 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange,
break;
}
+ // If the memory orders are constants, check they are valid.
if (SubExprs.size() >= 2 && Form != Init) {
- if (std::optional<llvm::APSInt> Result =
- SubExprs[1]->getIntegerConstantExpr(Context))
- if (!isValidOrderingForOp(Result->getSExtValue(), Op))
- Diag(SubExprs[1]->getBeginLoc(),
- diag::warn_atomic_op_has_invalid_memory_order)
- << SubExprs[1]->getSourceRange();
+ std::optional<llvm::APSInt> Success =
+ SubExprs[1]->getIntegerConstantExpr(Context);
+ if (Success && !isValidOrderingForOp(Success->getSExtValue(), Op)) {
+ Diag(SubExprs[1]->getBeginLoc(),
+ diag::warn_atomic_op_has_invalid_memory_order)
+ << /*success=*/(Form == C11CmpXchg || Form == GNUCmpXchg)
+ << SubExprs[1]->getSourceRange();
+ }
+ if (SubExprs.size() >= 5) {
+ if (std::optional<llvm::APSInt> Failure =
+ SubExprs[3]->getIntegerConstantExpr(Context)) {
+ if (!llvm::is_contained(
+ {llvm::AtomicOrderingCABI::relaxed,
+ llvm::AtomicOrderingCABI::consume,
+ llvm::AtomicOrderingCABI::acquire,
+ llvm::AtomicOrderingCABI::seq_cst},
+ (llvm::AtomicOrderingCABI)Failure->getSExtValue())) {
+ Diag(SubExprs[3]->getBeginLoc(),
+ diag::warn_atomic_op_has_invalid_memory_order)
+ << /*failure=*/2 << SubExprs[3]->getSourceRange();
+ }
+ }
+ }
}
if (auto ScopeModel = AtomicExpr::getScopeModel(Op)) {