diff options
author | Tim Northover <tnorthover@apple.com> | 2014-03-11 10:49:14 +0000 |
---|---|---|
committer | Tim Northover <tnorthover@apple.com> | 2014-03-11 10:49:14 +0000 |
commit | e94a34cae25e91aab4d9461fbca1cef89ed5d928 (patch) | |
tree | 09384bbfa97821e7518882a9f201e895b49109b1 /clang/lib/Sema/SemaChecking.cpp | |
parent | 0622b3a67af7545fa634c7fa98407f570a01d7b0 (diff) | |
download | bcm5719-llvm-e94a34cae25e91aab4d9461fbca1cef89ed5d928.tar.gz bcm5719-llvm-e94a34cae25e91aab4d9461fbca1cef89ed5d928.zip |
Sema: produce error when invalid ordering is passed to atomic builtin
This is a conservative check, because it's valid for the expression to be
non-constant, and in cases like that we just don't know whether it's valid.
rdar://problem/16242991
llvm-svn: 203561
Diffstat (limited to 'clang/lib/Sema/SemaChecking.cpp')
-rw-r--r-- | clang/lib/Sema/SemaChecking.cpp | 38 |
1 files changed, 37 insertions, 1 deletions
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 512916e9a8e..19e61b2e819 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -911,6 +911,33 @@ bool Sema::CheckOtherCall(CallExpr *TheCall, const FunctionProtoType *Proto) { return false; } +static bool isValidOrderingForOp(int64_t Ordering, AtomicExpr::AtomicOp Op) { + if (Ordering < AtomicExpr::AO_ABI_memory_order_relaxed || + Ordering > AtomicExpr::AO_ABI_memory_order_seq_cst) + return false; + + switch (Op) { + case AtomicExpr::AO__c11_atomic_init: + llvm_unreachable("There is no ordering argument for an init"); + + case AtomicExpr::AO__c11_atomic_load: + case AtomicExpr::AO__atomic_load_n: + case AtomicExpr::AO__atomic_load: + return Ordering != AtomicExpr::AO_ABI_memory_order_release && + Ordering != AtomicExpr::AO_ABI_memory_order_acq_rel; + + case AtomicExpr::AO__c11_atomic_store: + case AtomicExpr::AO__atomic_store: + case AtomicExpr::AO__atomic_store_n: + return Ordering != AtomicExpr::AO_ABI_memory_order_consume && + Ordering != AtomicExpr::AO_ABI_memory_order_acquire && + Ordering != AtomicExpr::AO_ABI_memory_order_acq_rel; + + default: + return true; + } +} + ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult, AtomicExpr::AtomicOp Op) { CallExpr *TheCall = cast<CallExpr>(TheCallResult.get()); @@ -1199,7 +1226,16 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult, SubExprs.push_back(TheCall->getArg(3)); // Weak break; } - + + if (SubExprs.size() >= 2 && Form != Init) { + llvm::APSInt Result(32); + if (SubExprs[1]->isIntegerConstantExpr(Result, Context) && + !isValidOrderingForOp(Result.getSExtValue(), Op)) + return ExprError(Diag(SubExprs[1]->getLocStart(), + diag::err_atomic_op_has_invalid_memory_order) + << SubExprs[1]->getSourceRange()); + } + AtomicExpr *AE = new (Context) AtomicExpr(TheCall->getCallee()->getLocStart(), SubExprs, ResultType, Op, TheCall->getRParenLoc()); |